2010-12-14 24 views
1

我有一個包含幾乎相同的數值組的列表。即(1004.523,1004.575,1004.475,791.385,791.298,791.301,791.305,791.299)基於Python中的模糊值縮小列表

我想要做的就是通讀列表並找到所有1004.5 +值聚合它們並找到平均值。然後繼續查找所有791.0 + - 值,並對它們執行相同操作。

我不知道每個「團隊」中會有多少個人價值觀,也不知道會有多少個團體。

我正在尋找的結果是另一個列表,其中將包含每個組的平均值。所以在這個例子中我的結果是(1004.524,791.3176)

我目前使用的代碼非常Kludgey,似乎應該有一個更好的方法來做到這一點。

正如你所看到的,我必須在else中重複一次代碼兩次,如果自從最後一組數字沒有觸發else,那麼一次結束。加上完成後,如果我需要添加最後一個值。

如果我使用len(音調)而不是len(音調)-i我得到超出範圍的錯誤。

任何想法或建議,將不勝感激。謝謝你的幫助。

埃德

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: 首先,我要感謝大家誰提交建議。答覆非常快速且有幫助。我應該可能在下面包含更多信息。非常感謝你的幫助。

其次,快速解釋我正在嘗試做什麼。我們當地的消防部門正在尋找一種方法來跟蹤接近他們的部門的派遣。大多數情況下,他們使用兩個音調順序尋呼,即1000Hz,然後是500Hz。

所以我使用numpy fft來查找音頻。由於音調的準確度似乎約爲±2 Hz,因此我將計算出的頻率與已知尋呼音列表進行比較,並選擇最接近的匹配。在所有音調與尋呼音匹配後,我會尋找與感興趣的部門匹配的信息。

有一件事我不知道什麼時候開始,在任何給定的調度中,同一個音可以重複多次,所以音的順序很重要。例如: 707.3,339.6,707.3,569.1,447.2,569.1將是一個典型的調度。然後我看看是否有任何音調對是我感興趣的,如果有的話,我會顯示一條消息

再次感謝您的幫助。

埃德

+0

你知道這些小組是多麼「廣泛」嗎(即,你是否將這個'2.0'拉出空中,或者是否可以推理出來)?這些團體能否「重疊」?就像有可能會有一系列不斷增加的價值相差很小,涵蓋範圍很廣嗎? – 2010-12-14 19:48:43

+0

通過查看我發現的數字,通常他們往往是+ -2Hz。這些數字是從聲卡採樣的結果。我目前每秒採樣7次,然後進行fft計算以確定主頻率。一般來說,第一個音長是1秒或大約7個樣本,第二個音是大約3秒長或大約21個樣本。通常有不止一組音調,所以模式會重複。我從來沒有聽過超過六套音調,所以一般來說,我認爲200可能是一個實際的限制。 – edwardb 2010-12-16 17:36:55

+0

感謝您對確切問題的補充信息,它有幫助。例如,我的解決方案不起作用,因爲它重新排序樣本。有一個問題,在嘗試對它們進行計數之前對它們進行分類不是更簡單嗎?匹配確切的等價物比近似的要容易得多。 – 2010-12-17 17:52:41

回答

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 2010-12-16 17:44:04

0

如果你知道什麼號碼可能出現的順序,你可以使用這個(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] 

分析序列不知道exacttones,像這將工作:

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'作弊。 – 2010-12-14 20:11:53

+0

@John同意,更新。 – khachik 2010-12-14 20:25:41

+0

我其實有一個已知的有效音調列表(約130)。我將試驗這個想法,看看它是否可行,因爲它將2個步驟合併爲1.感謝您的想法。 – edwardb 2010-12-16 17:49:48

3

也許您在尋找kmeans clustering

在下面的代碼中,我使用scipy.cluster.vq.kmeans將數據聚類到k組中。 如果失真大於某個設定的閾值量,則我們將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

我甚至沒有考慮過這個。自從我參加任何類型的數學課後,我已經許多年了。不幸的是,在我原來的問題中,我沒有提到相同的音調可能會不止一次地發生,音調順序至關重要。然而,你的想法確實解決了我正在處理的另一個問題,我爲此感謝你。 – edwardb 2010-12-16 17:41:01

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 2010-12-16 18:11:08

0

假設這是音調的列表,你可能需要使用一小部分,如1.059確定的範圍內分配到一組,而不是硬編碼了一些像2.0

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 2010-12-16 17:58:04

+0

@edwardb,如果頻率範圍足夠小或者您的聚類足夠緊湊,常數可能與乘數一樣好。我的常數有一個鏈接,點擊進入,你會看到我從哪裏挑選我的號碼 - 這是一個半音差異的乘數。回想起來,我應該選擇1.0295來將中心頻率兩側的範圍減半。 – 2010-12-16 20:24:14