Issue
I am importing data that comes in a list of N 1D arrays of [x,y,z] and I want to assign them to the diagonals of an N-dimensional array of shape [N,3,3].
The below works... it is very slow due to the loop. Is there a better way to do this via matrix operations?
import numpy as np
a=np.arange(6).reshape(2,3,1)
I=np.zeros((2,3,3))
points=a.shape[0]
for step in range(points):
np.fill_diagonal(I[step],a[step]
print(I)
[[[0., 0., 0.],
[0., 1., 0.],
[0., 0., 2.]],
[[3., 0., 0.],
[0., 4., 0.],
[0., 0., 5.]]]
Solution
Here's one approach (note that you should set the dtype
to fit your needs, I used 8-bit integers for the sake of memory):
I = np.zeros((2, 3, 3), dtype="uint8")
x, y, _ = I.shape
idxs = np.arange(y)
I[..., idxs, idxs] = np.arange(x * y).reshape(x, y)
Output:
In [4]: I
Out[4]:
array([[[0, 0, 0],
[0, 1, 0],
[0, 0, 2]],
[[3, 0, 0],
[0, 4, 0],
[0, 0, 5]]], dtype=uint8)
A slightly larger example:
In [5]: I = np.zeros((3, 6, 6), dtype="uint8")
In [6]: x, y, _ = I.shape
In [7]: idxs = np.arange(y)
In [8]: I[..., idxs, idxs] = np.arange(x * y).reshape(x, y)
In [9]: I
Out[9]:
array([[[ 0, 0, 0, 0, 0, 0],
[ 0, 1, 0, 0, 0, 0],
[ 0, 0, 2, 0, 0, 0],
[ 0, 0, 0, 3, 0, 0],
[ 0, 0, 0, 0, 4, 0],
[ 0, 0, 0, 0, 0, 5]],
[[ 6, 0, 0, 0, 0, 0],
[ 0, 7, 0, 0, 0, 0],
[ 0, 0, 8, 0, 0, 0],
[ 0, 0, 0, 9, 0, 0],
[ 0, 0, 0, 0, 10, 0],
[ 0, 0, 0, 0, 0, 11]],
[[12, 0, 0, 0, 0, 0],
[ 0, 13, 0, 0, 0, 0],
[ 0, 0, 14, 0, 0, 0],
[ 0, 0, 0, 15, 0, 0],
[ 0, 0, 0, 0, 16, 0],
[ 0, 0, 0, 0, 0, 17]]], dtype=uint8)
Some basic benchmarking:
In [10]: I = np.zeros((10000, 3, 3), dtype="uint8")
In [11]: x, y, _ = I.shape
In [12]: idxs = np.arange(y)
In [13]: %timeit I[..., idxs, idxs] = np.arange(x * y).reshape(x, y)
26.6 µs ± 61.7 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Answered By - ddejohn
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.