1

The problem

Create a higher dimensional NumPy array with zeros on the new dimensions

Details

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.

Simpler problem for better understanding

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.

2d to 3d case

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.

8
  • The last two axes of b are a squat array and you can achieve your result with a triangular matrix. When you say a = [1, 2], do you mean that you want each row of b to count down from each element of a down to 0 and then remain 0 for any leftover elements in the row? Is that 1-2 sequential? Could you have a = [1, 3, 2]? Commented Mar 5, 2021 at 13:03
  • I need to retain the sequence. I can have a=[1,3,2] but than we would have b = [[0,0,1],[0,1,3],[1,3,2]]. I don't see how to do with a triangular matrix. What I was trying is to append and delete elements and add to a new np.zeros array with more dimensions. Commented Mar 5, 2021 at 13:25
  • In the first example the numbers appear in reverse order, i.e., for [1, 2, 3..., 10], you get [1], [2, 1], [3, 2, 1], etc. But in your second example they appear in forward order, i.e., that would be [1], [1, 2], [1, 2, 3]. Which one do you want? Commented Mar 5, 2021 at 14:42
  • Both work for me but I prefer the reverse order. I will edit the question. Thanks. Commented Mar 5, 2021 at 14:46
  • Your example is only concerned with a[0,0]. Do you want a similar thing to happen for each index in the first two axes of your example, or just the specific ones? Commented Mar 5, 2021 at 14:53

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

9 Comments

This works for the arrays with one dimension but not for the 2-dimensional case and greater. For example if I have the a = np.array([[1,2,3],[1,2,3],[1,2,3]]) I would expect the result array b[0] = array([[[0., 0., 1.],[0., 1., 2.],[1., 2., 3.]], b[1] = array([[[0., 0., 1.],[0., 1., 2.],[1., 2., 3.]]. I tested the code and the result is b[1] = array([[2., 3., 1.],[3., 1., 2.],[1., 2., 3.]]).
Please precise your algorithm. Now, you would expect that b[0]==b[1].
It is not b[0]==b[1] for every scenario only for a = [[1,2,3],[1,2,3],[1,2,3]]. For the case where a = [[1,2,3],[4,5,6],[7,8,9]] , b[0] = [[0,0,1],[0,1,2],[1,2,3]], b[1] = [[0,0,4],[0,4,5],[4,5,6]].
Again, if I understand your algorithm correctly, please try the corrected code in my answer. I introduced tensor to transform your last dimension data.
Did you check current version of the code with tensor product in my answer? That's what you need?
|
0

I was able to solve the problem but there is probably a more efficient way to do it:

a = np.array([[1,2,3],[4,5,6],[7,8,9]]) #two  dim case

a = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]]])# three dim case

def increase_dim(arr):
    stack_list = []
    stack_list.append(arr)
    for i in range(1,arr.shape[-1]):
       stack_list.append(np.delete(np.delete(np.append(np.zeros(arr.shape),arr,axis=-1),np.s_[-i:],axis = len(arr.shape)-1),np.s_[:arr.shape[-1]-i],axis = -1))    
    return np.stack(stack_list,axis = -1)

b = increase_dim(b)

I hope this can help the question understanding.

1 Comment

Why did you swap a and b in this explanation?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.