【问题标题】:python: calculate center of masspython:计算质心
【发布时间】:2015-06-04 02:16:55
【问题描述】:

我有一个包含 4 列的数据集:x、y、z 和值,比方说:

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 坐标吗?

非常感谢任何帮助。

【问题讨论】:

  • 对不起这里的值有什么意义?这是群众吗?所以实际上你想要[1 1 0 1] [1 2 0 1]的平均值?
  • 好的,为什么不写一个函数来做这个呢?这是微不足道的数学。

标签: python numpy centering


【解决方案1】:

为什么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 的每个“像素”都需要在内存中实例化。

【讨论】:

    【解决方案2】:

    另一种选择是使用 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)
    

    【讨论】:

    • 问题已经说明 ndimage.measurements.center_of_mass 已尝试但未给出预期结果
    【解决方案3】:

    怎么样:

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

    【讨论】:

    • 这没有return,似乎没有正确的乘法维度,如果我修复这些,它似乎没有给出正确的答案。我错过了什么?
    【解决方案4】:

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

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

    【讨论】:

    • 我忘记了np.average 接受了权重参数!
    猜你喜欢
    • 2018-05-29
    • 1970-01-01
    • 1970-01-01
    • 2017-06-18
    • 2012-04-06
    • 2019-05-12
    • 2022-11-21
    • 1970-01-01
    相关资源
    最近更新 更多