【问题标题】:How to efficiently find clusters of like elements in a multidimensional array如何有效地在多维数组中找到相似元素的集群
【发布时间】:2015-12-17 02:56:48
【问题描述】:

我有一个像这样的多维数组:

array = [[a, b, b, a, a, b]
         [a, a, b, a, b, a]]

我想做的是识别相似元素的集群,即查看每个元素并根据其上方、下方、左侧或右侧是否有另一个“a”找到一组“a”,这样程序找到这样一个数组:

[a, b, b, a, a, b]

[a, a, b, a, b, a ]

它会为第一个'a'簇返回一个像这样的数组 ["0:0", "1:0", "1:1"]

我的问题是,在 python 中最有效的方法是什么?

仅供参考:我使用的是 Python 2.7

【问题讨论】:

  • 您想识别集群和集群元素的位置吗?还是您的目标只是测量每个集群的大小(每个集群包含的元素数量)?
  • @MartinValgur 对此感到抱歉;我想要的是返回一个数组,其中包含该集群中每个元素的位置(例如 return ["0:0", "1:0", "1:1"]

标签: python arrays python-2.7 multidimensional-array


【解决方案1】:

使用scipy.ndimage.measurements:

from scipy import ndimage 

def find_clusters(array):
    clustered = np.empty_like(array)
    unique_vals = np.unique(array)
    cluster_count = 0
    for val in unique_vals:
        labelling, label_count = ndimage.label(array == val)
        for k in range(1, label_count + 1):
            clustered[labelling == k] = cluster_count
            cluster_count += 1
    return clustered, cluster_count

clusters, cluster_count = find_clusters(array)
print("Found {} clusters:".format(cluster_count))
print(clusters)

ones = np.ones_like(array, dtype=int)
cluster_sizes = ndimage.sum(ones, labels=clusters, index=range(cluster_count)).astype(int)
com = ndimage.center_of_mass(ones, labels=clusters, index=range(cluster_count))
for i, (size, center) in enumerate(zip(cluster_sizes, com)):
    print("Cluster #{}: {} elements at {}".format(i, size, center))

产量:

Found 6 clusters:
[[0 3 3 1 1 4]
 [0 0 3 1 5 2]]
Cluster #0: 3 elements at (0.66666666666666663, 0.33333333333333331)
Cluster #1: 3 elements at (0.33333333333333331, 3.3333333333333335)
Cluster #2: 1 elements at (1.0, 5.0)
Cluster #3: 3 elements at (0.33333333333333331, 1.6666666666666667)
Cluster #4: 1 elements at (0.0, 5.0)
Cluster #5: 1 elements at (1.0, 4.0)

要获取每个集群中元素的位置,您可以使用clusters == cluster_id,例如

In [126]:
clusters == 3
Out[126]:
array([[False,  True,  True, False, False, False],
       [False, False,  True, False, False, False]], dtype=bool)

或者,要获取每个集群的边界框,您可以使用来自同一个 SciPy 包的find_objects

In [128]:
# +1 because zeros would be ignored otherwise
scipy.ndimage.measurements.find_objects(clusters+1)
Out[128]:
[(slice(0, 2, None), slice(0, 2, None)),
 (slice(0, 2, None), slice(3, 5, None)),
 (slice(1, 2, None), slice(5, 6, None)),
 (slice(0, 2, None), slice(1, 3, None)),
 (slice(0, 1, None), slice(5, 6, None)),
 (slice(1, 2, None), slice(4, 5, None))]

【讨论】:

  • 您能否让它返回指示它们在多维数组中的位置的簇?谢谢!
  • 我认为我的编辑现在涵盖了这一点。只需执行clusters == cluster_id 即可获取确切位置。
  • 谢谢。我可能需要一点时间来解决这个问题,但它看起来很棒:D
  • scipy.ndimage.measurements 中的函数也作为scipy.ndimage 中的函数公开。例如,您可以使用from scipy import ndimage 并调用ndimage.find_objects
  • @unutbu 谢谢!每隔一行显示完整的包名,它开始变得非常难看。
猜你喜欢
  • 2013-07-21
  • 2015-04-30
  • 2013-03-26
  • 1970-01-01
  • 2018-11-12
  • 2010-12-03
  • 2015-07-14
  • 1970-01-01
  • 2020-08-13
相关资源
最近更新 更多