3

我有很多 x,y 坐标,我根据它们之间的距离进行了聚类。现在我想为每个 x,y 坐标簇计算质心测量值。有没有办法做到这一点?

我的坐标格式为:

    coordinates_cluster = [[x1,x2,x3,...],[y1,y2,y3,...]]

每个簇的最小长度为三个点,并且所有点都可以有负和正的 x 和 y 值。我希望有人能帮助我。

最好的,马丁

(我在 Windows 7 系统上使用带有 canopy 1.1.1(32 位)的 python 2.7。)

4

3 回答 3

7

我意识到这并不难,但这里是计算 x,y 坐标质心的代码:

    >>> c = [[1,4,-5],[3,-2,9]] # of the form [[x1,x2,x3],[y1,y2,y3]]
    >>> centroide = (sum(c[0])/len(c[0]),sum(c[1])/len(c[1]))

    >>> centroide
    (0, 3)
于 2013-10-30T17:07:02.273 回答
6

恕我直言,此处给出的公认答案不适用于您想要计算由一组(x,y)顶点(又名多边形)定义的形状的质心的典型现实生活用例。所以请原谅我回答一个大约 8 年前提出的问题,但它仍然在我的 SO 搜索中名列前茅,所以它也可能会出现在其他人身上。我并不是说在问题的具体情况下接受的答案是错误的,但我认为,大多数找到这个线程的人实际上是根据不同的定义寻找质心。

质心未定义为顶点的算术平均值

...这与普遍看法相反。我们必须承认,通常通过质心,我们想到的是“图中所有点的算术平均位置”。非正式地,它是形状的切口可以在针尖上完美平衡的点”(引用维基百科,这里引用实际文献)。请注意,它是图中的所有点,而不仅仅是顶点坐标的平均值。这正是,如果您接受大多数 SO 答案,您将出错的地方,这意味着质心是顶点的 x 和 y 坐标的算术平均值,并将其应用于您可能通过执行实验收集的现实生活数据.
描述您的形状的点的密度可能会沿着您的形状线变化。这只是所述方法的许多可能的限制之一。那么坐标的简单平均值肯定不是你想要的。我将用一个例子来说明这一点。

例子

多边形示例
在这里,我们看到一个由 8 个顶点组成的多边形。我们的直觉正确地告诉我们,我们可以在 (x,y)=(0,0) 的针尖上平衡这个形状,使质心 (0,0)。但是在 (-1,1) 周围的区域中,我们用来描述该多边形的点/顶点的密度高于沿线的其他区域。现在,如果我们通过取顶点的平均值来计算质心,结果将被拉向高密度区域。
点“centroid poly”对应于真实的质心。这一点是通过实施此处描述的算法计算得出的:https ://en.wikipedia.org/wiki/Centroid#Of_a_polygon (唯一的区别:它返回区域的绝对值)
它适用于由 N 个顶点的 x 和 y 坐标描述的图形,例如 X = x_0, x_1, ..., x_(N-1),对于 Y 也是如此。这个图形可以是任何多边形,只要它是非自相交的并且顶点按出现的顺序给出。
这可用于计算例如 matplotlib 轮廓线的“真实”质心。

代码

这是上面示例的代码和所述算法的实现:

import matplotlib.pyplot as plt

def centroid_poly(X, Y):
    """https://en.wikipedia.org/wiki/Centroid#Of_a_polygon"""
    N = len(X)
    # minimal sanity check
    if not (N == len(Y)): raise ValueError('X and Y must be same length.')
    elif N < 3: raise ValueError('At least 3 vertices must be passed.')
    sum_A, sum_Cx, sum_Cy = 0, 0, 0
    last_iteration = N-1
    # from 0 to N-1
    for i in range(N):
        if i != last_iteration:
            shoelace = X[i]*Y[i+1] - X[i+1]*Y[i]
            sum_A  += shoelace
            sum_Cx += (X[i] + X[i+1]) * shoelace
            sum_Cy += (Y[i] + Y[i+1]) * shoelace
        else:
            # N-1 case (last iteration): substitute i+1 -> 0
            shoelace = X[i]*Y[0] - X[0]*Y[i]
            sum_A  += shoelace
            sum_Cx += (X[i] + X[0]) * shoelace
            sum_Cy += (Y[i] + Y[0]) * shoelace
    A  = 0.5 * sum_A
    factor = 1 / (6*A)
    Cx = factor * sum_Cx
    Cy = factor * sum_Cy
    # returning abs of A is the only difference to
    # the algo from above link
    return Cx, Cy, abs(A)

# ********** example ***********
X = [-1, -0.8,  -0.6,  1,   2,  1, -1,   -2]
Y = [ 1,    1,     1,  1, 0.5, -1, -1, -0.5]

Cx, Cy, A = centroid_poly(X, Y)

# calculating centroid as shown by the accepted answer
Cx_accepted = sum(X)/len(X)
Cy_accepted = sum(Y)/len(Y)

fig, ax = plt.subplots()
ax.scatter(X, Y, label='vertices')
ax.scatter(Cx_accepted, Cy_accepted, label="mean of vertices")
ax.scatter(Cx, Cy, label='centroid poly')

# just so the line plot connects xy_(N-1) and xy_0
X.append(X[0]), Y.append(Y[0])
ax.plot(X, Y, label='polygon')

ax.legend(bbox_to_anchor=(1, 1))
ax.grid(), ax.set_aspect('equal')
于 2021-06-25T10:46:08.763 回答
1

如果您有兴趣计算几何或信号处理[1 , 2]中定义的质心:

import numpy as np
# a line from 0,0 to 1,1
x = np.linspace(0, 1, 100)
y = np.linspace(0, 1, 100)
cx = np.dot(x, y) / np.sum(y)

0.67003367003367

在此处输入图像描述

于 2019-05-13T23:51:21.187 回答