"Transform" Numpy Arrray: Move Dimension - python

I'm creating array a:
import numpy as np
a = np.zeros((3, 10, 10), np.uint8)
a[1,5,5] = 255
with a red dot in the center, where the RGB is the first dimension. Then I plot it using matplotlib:
import matplotlib.pyplot as plt
plt.imshow(a)
But of course this doesn't work because imshow expects an array with dimensions (10, 10, 3) and I am feeding it an array with dimensions (3, 10, 10). How could I 'flip' the array so that the RGB is the third dimension, instead of the first?

What you need is swapaxes.
import numpy as np
a = np.zeros((3, 10, 10), np.uint8)
print(a.shape) #(3,10,10)
print(np.swapaxes(a,0,2).shape) #(10,10,3)
See documentation.
np.swapaxes(a,0,2) equals to np.transpose(a, (2,1,0)).
There is another option which is np.transpose(a, (1,2 0)).
As always, transpose matrix can have two versions which produce similar result but with different 3-dimensional rotational symmetry.
It depends on if the mirror matrix affect your result, you should carefully test if it makes difference.

Related

Append 2d array to 3d array

I have an array of shape (3, 250, 15).
I want to append to it a 2d array of shape (250,15) so that I have a final shape of (4,250,15).
I tried with dstack and np.stack but it does not work.
Can someone give me a suggestion ?
You need to add a dimension (in other words, an axis) to the 2-D array, for example:
import numpy as np
a = np.ones((3, 250, 15))
b = np.ones((250, 15))
c = np.vstack([a, b[None, :, :]])
Now c has shape (4, 250, 15).
If you're not into the None axis trick, you could achieve something similar with np.newaxis or np.reshape.
You can't append a 2D array to a 3D array directly, so you should first expand the axes of the smaller array to become 3D and then append normally. np.expand_dims(b, axis=0) will insert the missing first-axis to array b. Now append the two 3D arrays, np.append(a, b, axis=0).
import numpy as np
a = np.ones((3, 250, 15))
b = np.ones(( 250, 15))
b = np.expand_dims(b, axis=0)
c = np.append(a, b, axis=0)
which works as expected.
print(c.shape)
(4, 250, 15)

Element-wise multiplication of a 3D array with a 2D array

I have a portion of a RGB image as numpy array, the shape of which is (height, width, channel) = (5, 5, 3).
What I want to do with this is to get the sum of element-wise multiplication with 5x5 kernel matrix, channel by channel. So it should yield a vector of size 3.
My current solution is:
print(portion.shape) # (5, 5, 3)
print(kernel.shape) # (5, 5)
result = [(kernel * portion[:, :, channel]).sum() for channel in range(3)]
print(result.shape) # (3,)
How can I achieve the same result in a more efficient way, hopefully without for-loop?
I'll show here two methods of doing this. The first one is basically the "manual" version that relies on broadcasting, which is an important concept to understand for using numpy and similar libraries.
The second method is basically using the Einstein summation convention, which can be quite fast if used right.
import numpy as np
portion = np.zeros((5, 5, 3))
kernel = np.zeros((5, 5))
# alternative
result = np.sum(kernel[..., None] * portion, axis=(0,1))
print(result.shape)
# einsum method:
result = np.einsum('ij,ijk->k', kernel, portion)
print(result.shape)
Try it online!

Duplicating vector along an arbitrary number of dimensions

I want to repeat a 1D-array along the dimensions of another array, knowing that this number of dimensions can change.
For example:
import numpy as np
to_repeat = np.linspace(0, 100, 10)
base_array = np.random.random((24, 60)) ## this one can have more than two dimensions.
final_array = np.array([[to_repeat for i in range(base_array.shape[0])] for j in range(base_array.shape[1])]).T
print(final_array.shape)
# >>> (10, 24, 60)
How can this be extended to an array base_array with an arbitrary number of dimensions?
Possibly using numpy vectorized functions in order to avoid loops?
EDIT (bigger picture):
base_array is in fact of shape (10, 24, 60) (if we stick to this example), where the coordinates along the first dimension are the vector to_repeat.
I'm looking for the minimum along the first dimension of base_array, and create the array of corresponding coordinates, here of shape (24, 60).
You don't need final_array, you can get the result you want by:
to_repeat[base_array.argmin(0)]

Numpy: How to multiply (N,N) and (N,N,M,M) numpy arrays?

I want to multiply two numpy arrays. One numpy array is given by matrix of shape (10, 10) and the other is given by a matrix of matrices, i.e. shape (10, 10, 256, 256).
I now simply want to multiply each matrix in the second matrix of matrices with the corresponding component in the first matrix. For instance, the matrix at position (0, 0) in the second matrix shall be multiplied by the value at position (0, 0) in the first matrix.
Intuitively, this is not really complicated, but numpy does not seem to support that. Or at least I am not smart enough to make it work. The ValueError that is thrown says:
ValueError: operands could not be broadcast together with shapes (10,10) (10,10,256,256)
Can anybody of you help me please? How can I achieve what I want in a numpyy way.
You can use the NumPy einsum function, e.g., (using zeros arrays as dummies in this example):
import numpy as np
x = np.zeros((10, 10))
y = np.zeros((10, 10, 256, 256))
z = np.einsum("ij,ijkm->km", x, y)
print(z.shape)
(256, 256)
See here for a nice description of einsum's usage.

Removing last 2D array from 3D array

I have a three-dimensional numpy array with shape
(5,5,N)
When I add another 5x5 2D array to this 3D array using numpy.dstack the shape changes like
(5,5,N+1)
and so on. I would like to remove the last 2D array I've added to the stack, such that it goes back to having the shape
(5,5,N)
and possibly (5,5,N-1),(5,5,N-2),...,etc.
What is the most pythonic way to achive this?
I would index as follows:
import numpy as np
a = np.ones((5,5,5))
a.shape
(5, 5, 5)
b = np.ones((5, 5, 5))[:, :, :-1]
b.shape
(5, 5, 4)

Categories