Python 中的快速旋转点列表

Quickly rotating list of points in Python

我有一个点列表 (L1) 和一个使用 numpy 制作的旋转矩阵 (R1),如下所示

L1 = [[1.1,2.3,-5.5],[3.4,2.0,3.0]]
R1 = [[ 0.99214145 -0.09280282 -0.08392241]
 [-0.09280282 -0.09592336 -0.99105315]
 [ 0.08392241  0.99105315 -0.10378191]]

我想使用 R1 旋转 L1 中的每个点,但我在 L1 中有 >1000000 个点,而不是两个点。

我已经使用以下代码进行轮换,但是像 L1 这样的 30 个列表需要超过 8 分钟,我想知道是否有使用 numpy 或任何其他模块的更快方法。非常感谢。

#make new list of rotated points
rotatedpoints = []
#do the inverse rotation for each point in dome
for point in L1:
        rotatedpoint = list((np.dot(R1, point)) )
        rotatedpoints.append(rotatedpoint)

你可以在这里进行矩阵乘法,基本上矩阵乘法和每一行的向量乘法是一样的:

因此,您可以获得 rotatedpoints 的结果,就像在您的示例程序中一样:

rotatedpoints = L1 <b>@</b> np.transpose(R1)

您的 rotatedpoints 结果是:

>>> rotatedpoints
[[1.3394823640000002, 5.1280854950000005, 2.942537401], [2.93590806, -3.4805357580000003, 1.956096764]]

矩阵乘法结果为:

>>> L1 @ np.transpose(R1)
array([[ 1.33948236,  5.1280855 ,  2.9425374 ],
       [ 2.93590806, -3.48053576,  1.95609676]])

使用 L1 形状为 1'000'000×3 的浮点列表列表,运行 10 次,我们得到作为基准:

>>> timeit(f, number=10)
5.256122357001004

因此,我们可以在 525 毫秒内平均旋转 1'000'000 个点(这包括将 L1R1 转换为 numpy 数组),或者每个向量大约 0.5μs。

编辑:

numpy 对 np 数组的运算速度更快。考虑将列表转换为 numpy 数组。

In [72]: L1                                                                                     
Out[72]: [[1.1, 2.3, -5.5], [3.4, 2.0, 3.0]]

In [73]: R1                                                                                     
Out[73]: 
[[0.99214145, -0.09280282, -0.08392241],
 [-0.09280282, -0.09592336, -0.99105315],
 [0.08392241, 0.99105315, -0.10378191]]

In [75]: %timeit np.dot(L1, R1)                                                                 
7.81 µs ± 30 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [76]: L2 = np.array(L1)                                                                      

In [78]: R2 = np.array(R1)                                                                      

In [79]: %timeit np.dot(L2, R2)                                                                 
1.51 µs ± 7.72 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [80]: %timeit L2 @ R2                                                                        
3.35 µs ± 12.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

旧答案

您也可以考虑应用自己的点积函数。

In [8]: from operator import mul

In [11]: %timeit sum(map(mul, L1[0], R1[0])) # just to  see how long it takes                                                    
873 ns ± 1.82 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [6]: %timeit np.dot(L1[0], R1)                                                               
5.63 µs ± 29.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

我不太喜欢 numpy,虽然可能有更多的最佳解决方案,但可以肯定的是 np 在你有大量数据要操作的地方闪耀。如果您处理的是相对较小的阵列等,手工制作的解决方案可能是更好的选择。