I want a generic way to get each column from an ndarray so I can write them one at a time to another file. The file only accepts 1 column at a time. I also need to know the index numbers for the yz coordinates to construct new names for column.
The input file contains many ndarrays which are mostly 1 dimensional. But, some are 2D or 3D arrays. I am trying to find a generic way to handle n dimensions. The code below works for a 3D array (x = rows, y = cols, z = depth).
import numpy as np
curve = np.arange(5000).reshape(10, 4,125)
if len(curve.shape) > 1:
for i, x in np.ndenumerate(curve[0,...]):
d = curve[:, i[0], i[1]]
s = '_' + '_'.join(str(e) for e in i)
print("Vp" + s)
Slicing the "top" row off gives an object that preserves the yz indices in an order to iterate columns.
For a tuple of indices, such as i = (y,z), I have to reference the values of i for indices to use with the : operator. This returns 500 (4 x 125) ndarrays with shape (10,). Success.
d = curve[:, i[0], i[1]]
If I could combine the tuple i with the slice operator I could process any ndarray shape. Substituting the following line instead
d = curve[:, i]
This sort of works but stops with the error below.
So,
Error using curve[:, i]
(10, 4, 125) <- Shape of input 3D ndarray
Index tuple: (0, 0) extracted ndarray of shape(10, 2, 125)
Vp_0_0
Index tuple: (0, 1) extracted ndarray of shape(10, 2, 125)
Vp_0_1
Index tuple: (0, 2) extracted ndarray of shape(10, 2, 125)
Vp_0_2
Index tuple: (0, 3) extracted ndarray of shape(10, 2, 125)
Vp_0_3
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-84-2aa0e9bae9df> in <cell line: 0>()
6 if len(curve.shape) > 1:
7 for i, x in np.ndenumerate(curve[0,...]):
----> 8 d = curve[:, i]
9 print("Index tuple: " + str(i) + " extracted ndarray of shape" + str(d.shape))
10 s = '_' + '_'.join(str(e) for e in i)
IndexError: index 4 is out of bounds for axis 1 with size 4
When you do
curve[:, i]
you are indexing with a tuple where the first element is a slice, and the second element is a tuple. This will invoke advanced indexing.
You could do
curve[:, *i]
to “explode” i
at the current level.
To build such an indexing tuple programatically, you cannot say, for example
i = (1, :, 2) # won’t work
because :
only works at the top level of a slicing. Instead, you can use the built-in slice()
function to create a slice object:
A = np.arange(27).reshape(3, 3, 3)
i = (1, slice(None), 1)
A[i] # => 10, 13, 16