在Pandas中使用矩阵进行最有效的行乘法

时间:2016-09-05 15:30:06

标签: python pandas numpy matrix

假设我有一个矩阵

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

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

首先应用df.reshape - 此示例中的每一行都包含三个3D坐标,因为[(x,y,z),(x,y,z),(x,y,z)]:< / p>

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

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

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

1 个答案:

答案 0 :(得分: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

enter image description here