2013-02-09 56 views
10

我已經使用了Google搜索功能,我已經測試過了,並且這讓我在智能手機的最後階段。我有一個我需要按照相似性進行分組的數字列表。例如,在[1,6,9,100,102,105,109,134,139]的列表中,1 6 9將被放入列表中,100,102,105和109將被放入列表,以及134和139.我在數學上很糟糕,我嘗試過並嘗試過,但是我無法實現它。爲了儘可能明確,我希望將相距10個數值的數字進行分組。誰能幫忙?謝謝。在Python中對數字進行分組/編號

+4

您需要更精確地定義「相似性」。你的意思是,有幾百位和幾十位數字? – 2013-02-09 01:26:26

+0

我的意思是,在彼此的10個(或者是多個)值內的數字。對不起,試圖儘可能明確地加以說明。 – 2013-02-09 01:28:59

+1

如果可能的組重疊? – millimoose 2013-02-09 01:30:31

回答

21

有很多方法可以做cluster analysis。一個簡單的方法是看該間隙大小的連續數據元素之間:

def cluster(data, maxgap): 
    '''Arrange data into groups where successive elements 
     differ by no more than *maxgap* 

     >>> cluster([1, 6, 9, 100, 102, 105, 109, 134, 139], maxgap=10) 
     [[1, 6, 9], [100, 102, 105, 109], [134, 139]] 

     >>> cluster([1, 6, 9, 99, 100, 102, 105, 134, 139, 141], maxgap=10) 
     [[1, 6, 9], [99, 100, 102, 105], [134, 139, 141]] 

    ''' 
    data.sort() 
    groups = [[data[0]]] 
    for x in data[1:]: 
     if abs(x - groups[-1][-1]) <= maxgap: 
      groups[-1].append(x) 
     else: 
      groups.append([x]) 
    return groups 

if __name__ == '__main__': 
    import doctest 
    print(doctest.testmod()) 
+0

這裏有我的解決方案。非常感謝。我會研究這段代碼的每個字符,哈哈。 – 2013-02-09 01:42:07

3

這將找到組:

nums = [1, 6, 9, 100, 102, 105, 109, 134, 139] 
for k, g in itertools.groupby(nums, key=lambda n: n//10): 
    print k, list(g) 

0 [1, 6, 9] 
10 [100, 102, 105, 109] 
13 [134, 139] 

注意,如果NUMS實際上不是歸類爲您的樣本顯示,你就必須先解決它。

+5

我不喜歡這種方法的唯一情況是''[1,6,9,99,100,134,139]''會將* 99 *和* 100 *分組到不同的組中。計算連續數據點之間的差異以確定一個簇開始和另一個結束的位置會更好。 – 2013-02-09 01:39:16

+1

是的不幸的是,當我嘗試這段代碼時發生了什麼; /。幾乎完美。 – 2013-02-09 01:44:50

+1

是的,我寫的時候沒有詳細說明。 – 2013-02-09 02:12:11

2

首先,可以很容易地轉換的任何序列爲對相鄰項的序列。只需開球,將其向前移動,然後拉開未移位和未移位的副本。唯一的問題是,你需要啓動或者(<something>, 1)(139, <something>),因爲在這種情況下,我們要的不是每對元素的,但對每個元素:

def pairify(it): 
    it0, it1 = itertools.tee(it, 2) 
    first = next(it0) 
    return zip(itertools.chain([first, first], it0), it1) 

(這不是最簡單的方法寫出來,但我認爲這可能是最可讀的人誰不熟悉itertools的方式。)

>>> a = [1, 6, 9, 100, 102, 105, 109, 134, 139] 
>>> list(pairify(a)) 
[(1, 1), (1, 6), (6, 9), (9, 100), (100, 102), (102, 105), (105, 109), (109, 134), (134, 139)] 

然後,斯內德爾德的主要的稍微複雜些的版本,你可以只使用groupby

但是,我認爲在這種情況下,這最終會比做同樣事情的顯式生成器更復雜。

def cluster(sequence, maxgap): 
    batch = [] 
    for prev, val in pairify(sequence): 
     if val - prev >= maxgap: 
      yield batch 
      batch = [] 
     else: 
      batch.append(val) 
    if batch: 
     yield batch 
相關問題