Numpy slicing with container (e.g. tuple or list) - python

I am trying to slice a nD numpy.ndarray. Assume that it is 3D for the sake of simplicity (but in fact it could have been 4D, 5D, etc.) and is composed by nx, ny, nz dimensions.
I would like to extract all nx rows for a given point ny, nz, using a container (e.g. a tuple or list) to select ny and nz.
Example:
Say I have a 3D array X of dimension: (46841, 128, 20), and I have a container = (127,11)
Desired solution:
x_selected = X[:,container]
where x_selected should have dimensions (46841,)

x_selected = X[(slice(None),) + container]
You can thus index X array with any tuple that contains a mixture of slices and integers. slice is just a pure python object described here. This tuple for indexing should have not more elements than dimensions of X array.

you can just use this :
x_selected=X[:,container[0],container[1]]
I tried with this :
A=np.zeros((3,5,7))
A[1,2,:].shape
And I got (7,) as the output

Related

Element wise divide like MATLAB's ./ operator?

I am trying to normalize some Nx3 data. If X is a Nx3 array and D is a Nx1 array, in MATLAB, I can do
Y = X./D
If I do the following in Python, I get an error
X = np.random.randn(100,3)
D = np.linalg.norm(X,axis=1)
Y = X/D
ValueError: operands could not be broadcast together with shapes (100,3) (100,)
Any suggestions?
Edit: Thanks to dm2.
Y = X/D.reshape((100,1))
Another way is to use scikitlearn.
from sklearn import preprocessing
Y = preprocessing.normalize(X)
From numpy documentation on array broadcasting:
When operating on two arrays, NumPy compares their shapes
element-wise. It starts with the trailing (i.e. rightmost) dimensions
and works its way left. Two dimensions are compatible when
they are equal, or
one of them is 1
Both of your arrays have the same first dimension, but your X array is 2-dimensional, while your D array is 1-dimensional, which means the shapes of these two arrays do not meet the requirements to be broadcast together.
To make sure they do, you could reshape your D array into a 2-dimensional array of shape (100,1), which would satisfy the requirements to broadcast: rightmost dimensions are 3 and 1 (one of them is 1) and the other dimensions are equal (100 and 100).
So:
Y = X/D.reshape((-1,1))
or
Y = X/D.reshape((100,1))
or
Y = X/D[:,np.newaxis]
Should give you the result you're after.

Advanced Indexing in 3 Dimensional Numpy ndarray In Python

I have a ndarray of shape (68, 64, 64) called 'prediction'. These dimensions correspond to image_number, height, width. For each image, I have a tuple of length two that contains coordinates that corresponds to a particular location in each 64x64 image, for example (12, 45). I can stack these coordinates into another Numpy ndarray of shape (68,2) called 'locations'.
How can I construct a slice object or construct the necessary advanced indexing indices to access these locations without using a loop? Looking for help on the syntax. Using pure Numpy matrixes without loops is the goal.
Working loop structure
Import numpy as np
# example code with just ones...The real arrays have 'real' data.
prediction = np.ones((68,64,64), dtype='float32')
locations = np.ones((68,2), dtype='uint32')
selected_location_values = np.empty(prediction.shape[0], dtype='float32')
for index, (image, coordinates) in enumerate(zip(prediction, locations)):
selected_locations_values[index] = image[coordinates]
Desired approach
selected_location_values = np.empty(prediction.shape[0], dtype='float32')
correct_indexing = some_function_here(locations). # ?????
selected_locations_values = predictions[correct_indexing]
A straightforward indexing should work:
img = np.arange(locations.shape[0])
r = locations[:, 0]
c = locations[:, 1]
selected_locations_values = predictions[img, r, c]
Fancy indexing works by selecting elements of the indexed array that correspond to the shape of the broadcasted indices. In this case, the indices are quite straightforward. You just need the range to tell you what image each location corresponds to.

Python/Numpy: How to extract interior of any dimension of numpy array?

Suppose I have a numpy array A which can be of any dimensions len(A.shape) can be 1,2,3,..etc. and a corresponding array, crop which len(crop) = len(A.shape) and I want to extract the interior values of A using crop. Here is an example for 2D array.
A = np.random.rand(30).reshape([5,6])
crop = np.array([1,2])
Wanted output:
A[crop[0]:-crop[0], crop[1]:-crop[1])
Assuming value of crop will be reasonable with respect to size of A. How do I do this for any dimension of array A ?
Here's one way with slice notation -
A[tuple([slice(i,-i,None) for i in crop])]
Or with the shorthand np.s_ -
A[tuple([np.s_[i:-i] for i in crop])]
If the start and end indices are given for each dimension, we can do something like as shown in Slicing NumPy array given start and end indices for generic dimensions.

Appending matricies into a single matrix with numpy

I have a function in Python that returns a numpy.mat of shape (100, 1). I am calling this function 4 times in a loop and would like to take the resulting 4 matricies and create a matrix of shape (100, 4). I have looked for sometime at numpy.append, numpy.concatenate, and numpy.insert but have not been able to get this working.
Here is a short SSCCE of my issue
zeros = np.zeros(shape=(100, 4))
for i in range(1, 5):
np.append(zeros, np.empty(shape=(100, 1)))
print(zeros)
Where zeros should results in a matrix of shape (100, 4) with "junk" values from each of the calls to numpy.empty and not all 0..
Do something along these lines -
zeros = np.zeros(shape=(100, 4))
for i in range(1, 5):
data = np.random.rand(100,1) # func that returns (100,1) shaped array
zeros[:,i-1] = data.ravel()
In place of ravel(), we could also use : data[:,0] or np.squeeze(data), basic idea is to feed a 1D array there, because the LHS zeros[:,i-1] expects a 1D array there.
As an alternative, inside the loop, we could also do -
zeros[:,[i-1]] = data
Thus, with that list of column index [i-1] instead of i-1, we are keeping the dimensions into which data is to be assigned (keeps as 2D) and that allows us to feed in data, which is also 2D without any change.

numpy.concatenate multidimensional arrays

I'm searching for an algorithm to merge a given number of multidimensional arrays (each of the same shape) to a given proportion (x,y,z).
For example 4 arrays with the shape (128,128,128) and the proportion (1,1,4) to an array of the shape (128,128,512).
Or 2 arrays with the shape (64,64,64) and the proportion (1,2,1) to an array of the shape (64,128,64)
I know how to do it manually with np.concatenate, but I need a general algorithm to do this. (np.reshape doesn't work - this will mess up the order)
edit: It's possible that the proportion is (1,2,3), then it is necessary to compare the left_edge of the box, to know where to place it. every array have a corresponding block with the attribute left_edge (xmin, ymin, zmin). Can I solve this with a if-condition?
If your proportion is always one-dimensional (i.e. concatenate in one dimension only), you can use this:
arrays = [...]
proportion = (1,1,4)
np.concatenate(arrays, axis=next(i for i,p in enumerate(proportion) if p>1))
Otherwise you have to explain what to do with proportion = (1,2,3)
Okay I programmed it this way and it seems to work. Maybe not the nicest way, but it do what I want.
blocks.sort(key=lambda x: (x.left_edge[2],x.left_edge[1],x.left_edge[0]))
proportion = (Nx * nblockx, Ny * nblocky, Nz * nblockz)
arrays = np.zeros((nblockx, nblocky, nblockz, Nx, Ny, Nz))
for block, (x,y,z) in zip(root_list,
product(range(nblockx),
range(nblocky),
range(nblockz))):
array = np.zeros((Nx, Ny, Nz), dtype = np.float64)
# this is only the function to fill the array
writearray(array, ...)
arrays[x,y,z] = array
shape = arrays.shape
array = np.zeros((shape[0]*shape[3], shape[1]*shape[4], shape[2]*shape[5]))
for x,y,z in product(range(shape[0]), range(shape[1]), range(shape[2])):
slicex = slice(x*shape[3], (x+1)*shape[3])
slicey = slice(y*shape[4], (y+1)*shape[4])
slicez = slice(z*shape[5], (z+1)*shape[5])
array[slicex, slicey, slicez] = arrays[x,y,z]
return array

Categories