【问题标题】:Most efficient row multiplication with matrix in PandasPandas 中最有效的矩阵行乘法
【发布时间】:2017-01-13 00:15:33
【问题描述】:

假设我有一个这样的矩阵

df = pd.DataFrame(randint(2,size=(3,9)))
df.values
array([[0, 1, 0, 1, 1, 1, 0, 1, 1],
       [1, 0, 1, 1, 1, 1, 0, 0, 1],
       [0, 0, 0, 1, 0, 0, 1, 1, 0]])

再次;本例中的每一行代表三个 3D 坐标,需要旋转,例如以下旋转矩阵:

array([[  0.00000000e+00,   0.00000000e+00,   1.00000000e+00],
       [  0.00000000e+00,   1.00000000e+00,   0.00000000e+00],
       [ -1.00000000e+00,   0.00000000e+00,   0.00000000e+00]])

为了尽可能高效地做到这一点(真正的问题有数百万个坐标顺便说一句),我有点困惑,我必须这样做:

首先应用df.reshape - 此示例中的每一行由三个 3D 坐标组成,如 [(x,y,z),(x,y,z),(x,y,z)]:

array([[0, 1, 0],
       [1, 1, 1],
       [0, 1, 1],
       [1, 0, 1],
       [1, 1, 1],
       [0, 0, 1],
       [0, 0, 0],
       [1, 0, 0],
       [1, 1, 0]])

那么为了得到rotate to convention,必须取u_new = R \dot u,这意味着上面的转置,这样我们就可以与旋转矩阵进行列(即坐标)乘法。

array([[0, 1, 0, 1, 1, 0, 0, 1, 1],
       [1, 1, 1, 0, 1, 0, 0, 0, 1],
       [0, 1, 1, 1, 1, 1, 0, 0, 0]])

然后我们可以做乘法:

pd.DataFrame(dot(rotmat,df)).values

array([[  0.00e+00,   2.22e-16,   0.00e+00,   1.00e+00,   2.22e-16,
          2.22e-16,   1.00e+00,   1.00e+00,   2.22e-16],
       [  1.00e+00,   0.00e+00,   1.00e+00,   1.00e+00,   1.00e+00,
          1.00e+00,   0.00e+00,   0.00e+00,   1.00e+00],
       [  0.00e+00,  -1.00e+00,   0.00e+00,  -1.00e+00,  -1.00e+00,
         -1.00e+00,   2.22e-16,  -1.00e+00,  -1.00e+00]])

然后将整个过程反转,使其恢复原始形状,以用于其他目的。

肯定有更有效的方法来做到这一点(希望不会弄乱旋转矩阵)?

【问题讨论】:

  • 我建议你使用 numpy 而不是 pandas 来处理几何变换,看看这个library。事实上,如果您正在寻找速度,请将数据传输到 GPU 并在那里进行转换
  • 当然可以,但是我没有在 pandas 中进行转换,dot 来自 numpy,然后我将其存储在最后的 pandas 数据框中。
  • @BPL 写的是真的。由于您在询问效率,因此最好在 numpy 中执行所有操作。创建数据帧会产生开销;将所有数据保存在一个 numpy 数组中并避免推入和拉入其他数据结构的成本会更有效。
  • @James 这个我明白了,我不是在pandas里做操作;它是在 numpy 中完成的。我的库的性质是无论如何它都必须重新存储在 pandas 数据框中。
  • numpy 中重塑和转置很快。矩阵乘积工具是dottransdoteinsummatmul (@)。对于简单的情况,dot 是最快的,因为它使用了优化的库。

标签: python pandas numpy matrix


【解决方案1】:

在您完成转换之前,这不应该触及数据框。

a = np.array([
        [0, 1, 0, 1, 1, 1, 0, 1, 1],
        [1, 0, 1, 1, 1, 1, 0, 0, 1],
        [0, 0, 0, 1, 0, 0, 1, 1, 0]
    ])

rotmat = np.array([
        [  0.00000000e+00,   0.00000000e+00,   1.00000000e+00],
        [  0.00000000e+00,   1.00000000e+00,   0.00000000e+00],
        [ -1.00000000e+00,   0.00000000e+00,   0.00000000e+00]
    ])

a.reshape(3, 3, -1).dot(rotmat).reshape(-1, 9)

array([[ 0.,  1.,  0., -1.,  1.,  1., -1.,  1.,  0.],
       [-1.,  0.,  1., -1.,  1.,  1., -1.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  1.,  0.,  1.,  1.]])

df = pd.DataFrame(a.reshape(3, 3, -1).dot(rotmat).reshape(-1, 9))
df

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    • 2018-07-05
    • 2013-09-14
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    相关资源
    最近更新 更多