簡體   English   中英

Python位屏蔽和點簇/原點組

[英]Python bitmasking and point cluster/group of origin

我正在嘗試找出最好的方法,以便使用Python從數據集和群集集創建位掩碼,以便每個群集集將替換原始集中的點的索引。

例如:

data = [[10,10],[20,20],[5,3],[7,2],[90,78]] #Data of length 5
clusters = [[[10,10],[20,20]],[[5,3],[7,2],[90,78]]] #List containing two clusters (cluster 0 and cluster 1)

output = [0,0,1,1,1] 

基本上,輸出應該顯示原始數據中每個點所在的群集。我現在剛剛熟悉map函數,並認為可以使用它,只是不確定如何使用。

data = [[10,10],[20,20],[5,3],[7,2],[90,78]] #Data of length 5
clusters = [[[10,10],[20,20]],[[5,3],[7,2],[90,78]]] #List containing two clusters (cluster 0 and cluster 1)

gen = (count for count, y in enumerate(clusters) for x in data if x in y)
output = list(gen)

這是一個執行相同操作的生成器表達式。

將點對轉換為元組而不是列表,使我們可以將每個點用作字典中的鍵(因為鍵必須是可哈希的),其原點簇為值

data = [[10,10],[20,20],[5,3],[7,2],[90,78]]
clusters = [[[10,10], [20,20]], [[5,3], [7,2], [90,78]]]
cd = dict((tuple(p), i) for i, cl in enumerate(clusters) for p in cl)
output = [cd[tuple(p)] for p in data] # output = list(map(lambda p: cd[tuple(p)], data))
print(output)

產生

[0, 0, 1, 1, 1]

性能

出於好奇,我將自己的解決方案與@ Back2Basics進行了比較,以了解兩者在數據量不斷增長的情況下的擴展程度。

以下實用程序函數生成一個由N x N個點組成的數據集,並將其划分為相等大小的簇

def gen_data(n):
    return [[x, y] for x in range(n) for y in range(n)]

def gen_clusters(data, c_size):
    g = [iter(data)]*c_size
    return [list(c) for c in zip(*g)]

這是兩個解決方案:

def ck_pynchia(data, clusters):
    cd = dict((tuple(p), i) for i, cl in enumerate(clusters) for p in cl)
    output = [cd[tuple(p)] for p in data]
    return output

def ck_b2b(data, clusters):
    gen = (count for count, y in enumerate(clusters) for x in data if x in y)
    output = list(gen)
    return output

現在讓他們計時

數據集為10 * 10點

python3 -mtimeit 'import clusters as cl; data = cl.gen_data(10); clusters = cl.gen_clusters(data, 10); cl.ck_pynchia(data,clusters)'
10000 loops, best of 3: 73.2 usec per loop

python3 -mtimeit 'import clusters as cl; data = cl.gen_data(10); clusters = cl.gen_clusters(data, 10); cl.ck_b2b(data,clusters)'
1000 loops, best of 3: 330 usec per loop

數據集為50 * 50點

python3 -mtimeit 'import clusters as cl; data = cl.gen_data(50); clusters = cl.gen_clusters(data, 50); cl.ck_pynchia(data,clusters)'
1000 loops, best of 3: 1.59 msec per loop

python3 -mtimeit 'import clusters as cl; data = cl.gen_data(50); clusters = cl.gen_clusters(data, 50); cl.ck_b2b(data,clusters)'
10 loops, best of 3: 177 msec per loop

數據集為100 * 100點

python3 -mtimeit 'import clusters as cl; data = cl.gen_data(100); clusters = cl.gen_clusters(data, 100); cl.ck_pynchia(data,clusters)'
100 loops, best of 3: 6.37 msec per loop

python3 -mtimeit 'import clusters as cl; data = cl.gen_data(100); clusters = cl.gen_clusters(data, 100); cl.ck_b2b(data,clusters)'
10 loops, best of 3: 2.82 sec per loop

如我們所見,這兩種算法的計算復雜度完全不同。

最后說明:如果您可以將點保存在元組而不是列表中,則操作會變得更加簡單和快捷:

data = [(10,10),(20,20),(5,3),(7,2),(90,78)]
clusters = [[(10,10), (20,20)], [(5,3), (7,2), (90,78)]]

cd = dict((p,i) for i, cl in enumerate(clusters) for p in cl)
output = [cd[p] for p in data] # output = list(map(lambda p: cd[p], data))

您可以通過以下方式做到這一點:

[idx for d in data for (c, idx) in zip(clusters, range(len(clusters))) if d in c]

如果您堅持使用map函數,則可以執行以下操作:

list(
    map(lambda tup: tup.index(True), 
        map(lambda d: list(map(lambda c: d in c, clusters)), data)
    )
)

內部映射生成一個列表列表:對於數據中的每個元素,都有一個True或False值列表,顯示該值是否包含在相應的群集中。

[[True, False], [True, False], [False, True], [False, True], [False, True]]

外部映射給出內部列表中首次出現的True的索引,該索引恰好是該數據元素的簇的索引。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM