Create a higher dimensional NumPy array with zeros on the new dimensions
Analyzing the last dimension, the result is similar to this:
(not an actual code, just a didactic example)
a.shape = (100,2,10)
a[0,0,0]=1
a[0,0,1]=2
...
a[0,0,9]=10
b.shape = (100,2,10,10)
b[0,0,0,:]=[0,0,0,0,0,0,0,0,0,1]
b[0,0,1,:]=[0,0,0,0,0,0,0,0,2,1]
b[0,0,2,:]=[0,0,0,0,0,0,0,3,2,1]
...
b[0,0,2,:]=[10,9,8,7,6,5,4,3,2,1]
a -> b
The objective is to transform from a
into b
. The problem is that is not only filled with zeros but has a sequential composition with the original array.
Another way to visualize is using lower-dimensional arrays:
We have this:
a = [1,2]
And I want this:
b = [[0,1],[2,1]]
Using NumPy array and avoiding long for loops.
We have this:
a = [[1,2,3],[4,5,6],[7,8,9]]
And I want this:
b[0] = [[0,0,1],[0,2,1],[3,2,1]]
b[1] = [[0,0,4],[0,5,4],[6,5,4]]
b[2] = [[0,0,7],[0,8,7],[9,8,7]]
I feel that for the 4-dimensional problem only one for loop with 10 iterations is enough.
Try something like this in the framework of numpy
:
import numpy as np
# create transformation tensors
N = a.shape[-1]
sigma1 = np.zeros((N,N,N))
sigma2 = np.zeros((N,N,N))
E = np.ones((N,N))
for i in range(N):
sigma1[...,i] = np.diag(np.diag(E,N-1-i),N-1-i)
sigma2[N-1-i,N-1-i:,i] = 1
b1 = np.tensordot(a, sigma1, axes=([-1],[0]))
b2 = np.tensordot(a, sigma2, axes=([-1],[0]))
where sigma1
, sigma2
are the transformation tensors for which you can transform the data associated with the last dimension of a
as you want (the two versions you mentioned in your question and comments). Here the loop is only used to create the transformation tensor.
For a = [[1,2,3],[1,2,3],[1,2,3]]
, the first algorithm gives:
[[[0. 0. 1.] [0. 1. 2.] [1. 2. 3.]] [[0. 0. 4.] [0. 4. 5.] [4. 5. 6.]] [[0. 0. 7.] [0. 7. 8.] [7. 8. 9.]]]
and the last algorithm gives:
[[[0. 0. 1.] [0. 2. 1.] [3. 2. 1.]] [[0. 0. 4.] [0. 5. 4.] [6. 5. 4.]] [[0. 0. 7.] [0. 8. 7.] [9. 8. 7.]]]
Try to avoid lists and loops when using numpy
as they slow down the execution speed.