I have 4-dimensional array. I am going to turn it into a 1-dim array. I use numpy ravel and it works fin with the default parameters.
However I would also like the positions/indices in the 4-dim array.
I want something like this as row in my output.
x,y,z,w,value
With x being the first dimension of my initial array and so on.
The obvious approach is iteration, however I was told to avoid it when I can.
for i in range(test.shape[0]):
for j in range(test.shape[1]):
for k in range(test.shape[2]):
for l in range(test.shape[3]):
print(i,j,k,l,test[(i,j,k,l)])
It will be to slow when I use a larger dataset.
Is there a way to configure ravel to do this or any other approach faster than iteration.
CodePudding user response:
Use np.indices with sparse=False, combined with np.concatenate to build the array. np.indices provides the first n columns, and np.concatenate appends the last one:
test = np.random.randint(10, size=(3, 5, 4, 2))
index = np.indices(test.shape, sparse=False) # shape: (4, 3, 5, 4, 2)
data = np.concatenate((index, test[None, ...]), axis=0).reshape(test.ndim 1, -1).T
A more detailed breakdown:
indexis a(4, *test.shape)array, with one element per dimension.- To make
testconcatenatable withindex, you need to prepend a unit dimension, which is whattest[None, ...]does.Noneis synonymous withnp.newaxis, andEllipsis, or..., means "all the remaining dimensions". - When you concatenate along
axis=0, you are appendingtestto the array of indices. Each element ofindexalong the first axis is now a 5-element array containing the index followed by the value. The remaining axes reflect the shape oftest, but besides that, you have what you want. - The goal is to flatten out the trailing dimensions, so you get a
(5, N)array, whereN = np.prod(test.shape). Thats what the finalreshapedoes.test.ndim 1is the size of the index 1 for the value.-1can appear exactly once in a reshape. It means "product of all the remaining dimensions".
