2010-12-14 15 views
1

私はほぼ同じ数値のグループを含むリストを持っています。 (1004.523,1004.575,1004.475,791.385,719.298,791.301,791.305,791.299)Pythonのファジー値に基づいてリストを減らす

私がしようとしているのは、リストを読んで、すべての1004.5 +値を集計して平均値を見つけることです。続けてすべての791.0 +値を見つけ、同じ値を返します。

各グループにどれだけの値があるか分かりませんし、グループの数もわかりません。

私が探している結果は、各グループの平均値を含む別のリストです。したがって、私の結果は(1004.524、791.3176)

です。私が現在使用しているコードは非常にKludgeyなので、もっと良い方法があるはずです。

あなたが見ることができるように、最後の数字セットがelseをトリガーしないので、elseで1回、ifの最後で1回コードを繰り返す必要があります。私は最後の値を追加する必要がある場合の完了時にプラス。

len(トーン)-iではなくlen(トーン)を使用すると、範囲外のエラーが発生します。

ご意見やご提案をいただければ幸いです。ご協力いただきありがとうございます。

エド

toneLen = len(tones) -1 
    for i in range(0, toneLen): 
     if abs(tones[i]-tones[i+1]) <= 2.0: 
      tmpTones.append(tones[i]) 
     else: 
      freq = mean(tmpTones) 
      newTones.append(freq) 
      tmpTones = [] 
    tmpTones.append(tones[i+1]) 
    freq = mean(tmpTones) 
    newTones.append(freq)     
    tones = newTones 

UPDATE: まず、私は提案を提出したすべての人に感謝したいです。応答は非常に迅速かつ有用でした。私はおそらく私が下でやっているいくつかの情報を含んでいたはずです。助けてくれてありがとう。

次に、私が何をしようとしているかの簡単な説明。当社の消防署は、近くにある部署の派遣を追跡する方法を探しています。ほとんどの場合、2つのトーンシーケンシャルページング、すなわち1000Hzに続いて500Hzを使用する。

私はnumpy fftを使ってトーン周波数を見つけています。トーンの精度は約±2Hzであるように見えるので、計算された周波数を既知のページングトーンのリストと比較し、最も近いマッチングを選びます。すべてのトーンがページングトーンにマッチした後、私は興味のある部門とのマッチを探します。私はこれを始めたとき、私はいずれにも与えられていることを知りませんでした

ことの一つは、同じ音が数回繰り返すことができるので、トーンの順序が重要である派遣します。例: 707.3,339.6,707.3,569.1,447.2,569.1が典型的なディスパッチです。私はその後、トーン・ペアのいずれかが、私は、私はすべてのあなたの助けのために再度メッセージに

感謝を表示する場合に興味があるものですかどうかを確認します。

エド

+0

グループがどの程度「広い」ことができるか知っていますか(つまり、「2.0」を空中から引き出したのか、それとも推論できるものなのか)知っていますか?グループは「重なり合っていてもいい?同様に、巨大な一連の値が絶えず増加し、少量で離れていて、広い範囲をカバーできますか? –

+0

数字を見ると、一般に+ 2Hzの傾向にあることがわかりました。これらの数値は、サウンドカードからサンプリングした結果です。私は現在、毎秒7回サンプリングしてから、fft計算を行って優位周波数を決定しています。一般に、第1のトーンは1秒間、すなわち約7サンプル、第2のトーンは約3秒間、すなわち約21サンプルである。通常、複数のトーンセットが存在するため、パターンは繰り返されます。私は一度に6つ以上の音色を聞いたことがないので、一般的に200はおそらく実用的な限界であると言います。 – edwardb

+0

あなたの正確な問題に関する追加情報をお寄せいただきありがとうございます。サンプルを並べ替えるので、私の解決策はうまくいかないでしょう。 1つの質問、あなたがそれらをカウントしようとする前に、トーンを分類する方が簡単ではないでしょうか?おおよそのものと正確に等価なものをマッチさせる方がずっと簡単です。 –

答えて

1

これはほぼ同一値のグループ間の境界を検出し、元の上のスライスを使用して平均値を算出しますリスト。

tones = (1004.523, 1004.575, 1004.475, 791.385, 791.298, 791.301, 791.305, 791.299) 
splits = [i for i in range(1, len(tones)) if abs(tones[i-1] - tones[i]) > 2] 
splits = [0] + splits + [len(tones)] 
tones = [mean(tones[splits[i-1]:splits[i]]) for i in range(1, len(splits))] 
# [1004.5243333333333, 791.31759999999997] 
+0

これは私が探していた答えでした。それは美しく動作します。助けてくれてありがとう。 – edwardb

0

あなたは数字が順番に表示されることがあります知っている場合は、この(exacttonesは、期待値のリストである)を使用することができます:exacttonesを知らなくてもシーケンスを分析するには

tones = (1004.523, 1004.575, 1004.475, 791.385, 791.298, 791.301, 791.305, 791.299) 
exacttones = (1004.5, 791.3) 
limit = 0.2 
[sum(x)/len(x) for x in [[y for y in tones if abs((y-e))<=limit] for e in exacttones]] 
# [1004.5243333333333, 791.31759999999997] 

を、のようなものこれは動作します:

def calc(d, value): 
    for k in d: 
     if abs(k-value) <= limit: 
      d[k].append(value) 
      return d 
    d[value] = [value] 
    return d 
[sum(x)/len(x) for x in reduce(calc, values, {}).values()] 
# [1004.5243333333333, 791.31759999999997] 
+0

OPは "" "私はどれくらいのグループがあるのか​​知っていません" - "exacttones"は不正をしています。 –

+0

@John合意、更新されました。 – khachik

+0

私は実際には、知られている有効なトーン(約130)のリストを持っています。私はこのアイデアを実験して、2ステップを1つにまとめることができるため、実行可能かどうかを調べるつもりです。あなたの考えに感謝します。 – edwardb

3

おそらくあなたはkmeans clusteringを探しています。以下のコードで

、Iはkグループにデータをクラスタリングするscipy.cluster.vq.kmeansを使用します。 ひずみが設定されたしきい値よりも大きい場合は、kを1つ増やし、kmeansのクラスタリングをやり直します。合計歪みがthresholdより小さいグループが見つかるまで繰り返されます。

import scipy.cluster.vq as scv 
import numpy as np 
import collections 
def auto_cluster(data,threshold=0.1): 
    # There are more sophisticated ways of determining k 
    # See http://en.wikipedia.org/wiki/Determining_the_number_of_clusters_in_a_data_set 
    k=1 
    distortion=1e20 
    while distortion>threshold: 
     codebook,distortion=scv.kmeans(data,k) 
     k+=1 
    code,dist=scv.vq(data,codebook)  
    groups=collections.defaultdict(list) 
    for index,datum in zip(code,data): 
     groups[index].append(datum) 
    return groups 

data=np.array((1004.523, 1004.575, 1004.475, 791.385, 791.298, 791.301, 791.305, 791.299)) 
groups=auto_cluster(data)  
for index in groups: 
    print('{index}: ave({d}) = {ave}'.format(
     index=index, 
     d=','.join(map('{0:g}'.format,groups[index])), 
     ave=np.mean(groups[index])) 
     ) 

収率

0: ave(791.385,791.298,791.301,791.305,791.299) = 791.3176 
1: ave(1004.52,1004.58,1004.48) = 1004.52433333 
+0

私はこれを考慮していませんでした。私は何らかの数学の授業を取って以来、長年何年も続いています。残念なことに私の元の質問では、同じ音調が2回以上発生する可能性があることに言及しておらず、音階順序が重要です。しかし、あなたのアイデアは私が取り組んでいた別の問題を解決しました。 – edwardb

0

これは中間一時リストなしで行います

assert tones 
total = prev = tones[0] 
count = 1 
newlist = [] 
for i in xrange(1, len(tones)): 
    t = tones[i] 
    if abs(t - prev) <= DELTA: 
     total += t 
     count += 1 
     prev = t 
    else: 
     newlist.append(total/count) 
     total = prev = t 
     count = 1 
newlist.append(total/count) 
+0

あなたの考えをありがとう。私はそれを感謝します。ありがとう – edwardb

0

これはオーディオトーンのリストであると仮定すると、あなたはおそらく、むしろ2.0のような番号をハードコーディングするよりも、グループに割り当てる範囲を決定するために、このような1.059として分数を使用したいです。

def average_tones(tones): 
    threshold = 1.059 
    average = 0 
    count = 0 
    for tone in sorted(tones): 
     if count != 0 and tone >= average*threshold: 
      yield average 
      count = 0 
     average = (average * count + tone)/(count + 1) 
     count += 1 
    if count != 0: 
     yield average 
+0

私は非常にあなたが範囲の一部を提案する理由を知ることに興味があります。私が見ていたデータと一致するように見えたので、私は2.0を選んだ。分数がより良い理由はありますか?助けてくれてありがとう。 – edwardb

+0

@edwardb周波数の範囲が十分に小さいか、またはクラスタリングが十分に緊密である場合は、定数が乗数と同様に機能する可能性があります。私の定数にリンクがあり、クリックスルーすると、どこから番号を選んだのかがわかります。これは半音差の乗数です。振り返ってみると、中心周波数の両側の範囲を半分にするために、私は1.0295を選んだはずです。 –

関連する問題