python:计算质心

时间:2015-03-30 21:39:58

标签: python numpy centering

我有一个包含4列的数据集:x,y,z和value,让我们说:

x  y  z  value
0  0  0  0
0  1  0  0
0  2  0  0
1  0  0  0
1  1  0  1
1  2  0  1
2  0  0  0
2  1  0  0
2  2  0  0

我想计算所有值的质心CM = (x_m,y_m,z_m)。在本示例中,我希望将(1,1.5,0)视为输出。

我认为这一定是一个微不足道的问题,但我无法在互联网上找到解决方案。 scipy.ndimage.measurements.center_of_mass似乎是正确的,但不幸的是,函数总是返回两个值(而不是3)。另外,我找不到任何关于如何从数组中设置ndimage的文档:我会使用形状为(9,4)的numpy数组N吗?然后N [:,0]是x坐标吗?

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:8)

我能想到的最简单的方法是:只需找到每个组件贡献加权的质量组件坐标的平均值。

import numpy
masses = numpy.array([[0,  0,  0,  0],
[0,  1,  0,  0],
[0,  2,  0,  0],
[1,  0,  0,  0],
[1,  1,  0,  1],
[1,  2,  0,  1],
[2,  0,  0,  0],
[2,  1,  0,  0],
[2,  2,  0,  0]])

nonZeroMasses = masses[numpy.nonzero(masses[:,3])] # Not really necessary, can just use masses because 0 mass used as weight will work just fine.

CM = numpy.average(nonZeroMasses[:,:3], axis=0, weights=nonZeroMasses[:,3])

答案 1 :(得分:2)

怎么样:

#                   x      y     z  value
table = np.array([[ 5. ,  1.3,  8.3,  9. ],
                  [ 6. ,  6.7,  1.6,  5.9],
                  [ 9.1,  0.2,  6.2,  3.7],
                  [ 2.2,  2. ,  6.7,  4.6],
                  [ 3.4,  5.6,  8.4,  7.3],
                  [ 4.8,  5.9,  5.7,  5.8],
                  [ 3.7,  1.1,  8.2,  2.2],
                  [ 0.3,  0.7,  7.3,  4.6],
                  [ 8.1,  1.9,  7. ,  5.3],
                  [ 9.1,  8.2,  3.3,  5.3]])

def com(xyz, mass):
    mass = mass.reshape((-1, 1))
    return (xyz * mass).mean(0)

print(com(table[:, :3], table[:, 3]))

答案 2 :(得分:1)

另一种选择是使用scipy重心:

from scipy import ndimage
import numpy

masses = numpy.array([[0,  0,  0,  0],
[0,  1,  0,  0],
[0,  2,  0,  0],
[1,  0,  0,  0],
[1,  1,  0,  1],
[1,  2,  0,  1],
[2,  0,  0,  0],
[2,  1,  0,  0],
[2,  2,  0,  0]])

ndimage.measurements.center_of_mass(masses)

答案 3 :(得分:0)

为什么 ndimage.measurements.center_of_mass 没有给出预期的结果?

关键在于输入数据 masses 是如何由 4 元组 (x, y, z, value) 组成的数组表示的

# x   y   z   value
[[0,  0,  0,  0],
 [0,  1,  0,  0],
 [0,  2,  0,  0],
 [1,  0,  0,  0],
 [1,  1,  0,  1],
 [1,  2,  0,  1],
 [2,  0,  0,  0],
 [2,  1,  0,  0],
 [2,  2,  0,  0]]

此处的数组 masses 表示每个质量的 3-D 位置和权重。 但是请注意,这个 python 数组结构只是一个二维数组。它的形状是 (9, 4)。

您需要传递给 ndimage 以获得预期结果的输入是一个 3-D 数组,其中各处都包含零以及数组内适当坐标处的每个质量的权重,如下所示:

from scipy import ndimage
import numpy

masses = numpy.zeros((3, 3, 1))
#      x  y  z    value
masses[1, 1, 0] = 1
masses[1, 2, 0] = 1

CM = ndimage.measurements.center_of_mass(masses)
#  x    y    z
# (1.0, 1.5, 0.0)

这正是预期的输出。

请注意此解决方案(和 ndimage 库)的局限性在于它需要非负整数坐标。对于大体积和/或稀疏体积也不会有效,因为 ndimage 的每个“像素”都需要在内存中实例化。