Reputation: 47
I have a list (L1) of points and a rotation matrix (R1) made using numpy as shown below
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]]
I would like to rotate each point in L1 using R1, but instead of two points, I have >1000000 points in L1.
I have used the following code to do the rotations but they take in excess of 8 minutes for 30 lists like L1 and I would like to know if there is any faster way using numpy or any other module. Thank you so much.
#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)
Upvotes: 1
Views: 1540
Reputation: 477607
You can perform matrix multiplication here, basically matrix multiplication is the same as vector multiplication for each row:
You can thus obtain the result for your rotatedpoints
as in your sample program with:
rotatedpoints = L1 @ np.transpose(R1)
Your rotatedpoints
had as result:
>>> rotatedpoints
[[1.3394823640000002, 5.1280854950000005, 2.942537401], [2.93590806, -3.4805357580000003, 1.956096764]]
The matrix multiplication has as result:
>>> L1 @ np.transpose(R1)
array([[ 1.33948236, 5.1280855 , 2.9425374 ],
[ 2.93590806, -3.48053576, 1.95609676]])
With L1
a list of lists of floats with shape 1'000'000×3, and for 10 runs, we get as benchmarks:
>>> timeit(f, number=10)
5.256122357001004
We thus can rotate 1'000'000 points on average in 525 milliseconds (this includes converting L1
and R1
to numpy arrays), or approximately 0.5μs per vector.
Upvotes: 1
Reputation: 2946
EDIT:
numpy operates on np arrays much faster. Consider converting your lists to numpy arrays.
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)
OLD ANSWER:
You may consider applying your own dot product function too.
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)
I'm not into numpy much, there might be more optimal solutions though, but one thing for sure is np shines where you have huge amounts of data to operate on. If you're dealing with relatively small arrays etc, handmade solutions might be better options.
Upvotes: 1