Python位掩码和点簇/原点组

时间:2015-10-27 19:55:43

标签: python dictionary grouping cluster-analysis masking

我试图找出使用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函数,并认为我可以使用它,只是没有确定如何。

3 个答案:

答案 0 :(得分:0)

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)

这是一个生成相同内容的生成器表达式。

答案 1 :(得分:0)

将点对转换为元组而不是列表,允许我们将每个点用作字典中的键(因为键必须是可清除的),其原点簇作为值

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))

答案 2 :(得分:0)

你可以通过理解来做到这一点:

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

如果你坚持使用地图功能,你可以这样做:

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的索引,该索引恰好是该数据元素的集群的索引。