我有一个x,y坐标列表
我需要做的是将它们分成连续区域组
列表中的所有x,y坐标最终都属于特定组。
我目前有一个简单的算法,只需遍历每个点并找到所有相邻点(所以在x上坐标为+ -1,在y上为+ -1) 但是,在使用大型x,y列表时,它太慢了。
PS请记住,群组中间可能存在漏洞。
答案 0 :(得分:2)
您可以使用的一种简单方法是k-means clustering。 k -means将观察列表分区为k
个集群,其中每个点都属于具有最近均值的集群。如果您知道有k=2
个点组,那么这个方法应该可以很好地工作,假设您的点集合相当分离(即使它们有洞)。 SciPy has an implementation of k-means应该很容易应用。
以下是您可以执行的分析类型的示例。
# import required modules
import numpy as np
from scipy.cluster.vq import kmeans2
# generate clouds of 2D normally distributed points
N = 6000000 # number of points in each cluster
# cloud 1: mean (0, 0)
mean1 = [0, 0]
cov1 = [[1, 0], [0, 1]]
x1,y1 = np.random.multivariate_normal(mean1, cov1, N).T
# cloud 2: mean (5, 5)
mean2 = [5, 5]
cov2 = [[1, 0], [0, 1]]
x2,y2 = np.random.multivariate_normal(mean2, cov2, N).T
# merge the clouds and arrange into data points
xs, ys = np.concatenate( (x1, x2) ), np.concatenate( (y1, y2) )
points = np.array([xs, ys]).T
# cluster the points using k-means
centroids, clusters = kmeans2(points, k=2)
在拥有1200万个数据点的2012 MBA上运行此功能非常快:
>>> time python test.py
real 0m20.957s
user 0m18.128s
sys 0m2.732s
它也是100%准确(鉴于点云根本不重叠,这并不奇怪)。这是一些用于计算群集分配准确性的快速代码。唯一棘手的部分是我首先使用欧几里德距离来识别哪个星团的质心与原始数据云的平均值匹配。
# determine which centroid belongs to which cluster
# using Euclidean distance
dist1 = np.linalg.norm(centroids[0]-mean1)
dist2 = np.linalg.norm(centroids[1]-mean1)
if dist1 <= dist2:
FIRST, SECOND = 0, 1
else:
FIRST, SECOND = 1, 0
# compute accuracy by iterating through all 2N points
# note: first N points are from cloud1, second N points are from cloud2
correct = 0
for i in range(len(clusters)):
if clusters[i] == FIRST and i < N:
correct += 1
elif clusters[i] == SECOND and i >= N:
correct += 1
# output accuracy
print 'Accuracy: %.2f' % (correct*100./len(clusters))
答案 1 :(得分:2)
您要做的是在图像处理中查找连接组件。你有一个二进制图像,其中列表中的所有(x,y)像素都是1,而不是0的像素是。
您可以使用numpy / scipy将数据转换为2D二进制图像,然后调用ndimage.label查找连接的组件。
假设所有x和y都是&gt; = 0,你知道max_x和max_y,结果图像适合内存,然后是:
import numpy as np
from scipy import ndimage
image = np.zeros(max_x, max_y)
for x, y in huge_list_of_xy_points:
image[x, y] = 1
labelled = ndimage.label(image)
应该为您提供一个数组,其中组1中的所有像素都具有值1,组2中的所有像素都具有值2,等等。未经测试。
答案 2 :(得分:0)
首先,您可以使用相应的图表G(V, E)
识别问题:
点是顶点,当且仅当e
与A
“接近”时,点B
和点A
之间存在边B
,你可以在哪里定义“关闭”。
由于每个点只属于一个组,因此组形成不相交的集合,您可以使用简单的DFS将点分配给组。在图论中,潜在的问题称为Connected Components。
DFS的复杂性是线性的,即O(V + E)
。