Merge three numpy arrays, keep largest value - python

I want to merge three numpy arrays, for example:
a = np.array([[0,0,1],[0,1,0],[1,0,0]])
b = np.array([[1,0,0],[0,1,0],[0,0,1]])
c = np.array([[0,1,0],[0,2,0],[0,1,0]])
a = array([[0, 0, 1],
[0, 1, 0],
[1, 0, 0]])
b = array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
c = array([[0, 1, 0],
[0, 2, 0],
[0, 1, 0]])
Desired result would be to overlay them but keep the largest value where multiple elements are not 0, like in the middle.
array([[1, 1, 1],
[0, 2, 0],
[1, 1, 1]])
I solved this by iterating over all elements with multiple if-conditions. Is there a more compact and more beautiful way to do this?

You can try of stacking arrays together in extra dimension with Numpy np.dstack method
and extract the maximum value specific to added dimension
# Stacking arrays together
d = np.dstack([a,b,c])
d.max(axis=2)
Out:
array([[1, 1, 1],
[0, 2, 0],
[1, 1, 1]])

NumPy's np.ufunc.reduce allows to apply a function cumulatively along a given axis. We can just concatenate the arrays and reduce with numpy.maximum to keep the accumulated elementwise maximum:
np.maximum.reduce([a,b,c])
array([[1, 1, 1],
[0, 2, 0],
[1, 1, 1]])

Related

Reshaping a matrix (numpy array) when matrices are multiplied on individual elements

I am trying to multiply each element of a 2x2 matrix say [1,1],[1,1] with a 2x2 Identity matrix. The problem is that numpy puts the whole identity matrix as a separate sub index which is not the result I need to evaluate it further, I want it to have 4 rows and 4 columns but when I reshape it to (4,4), it offsets the values and I get [1,0,1,0] on each row (consult the image for required and obtained results).
Thank you!
Image here
EDIT:
Thanks for the response and code.
I made a mistake formulating my question so I'll try one more time.
I have a matrix
I = [[1,0],[0,1]]
A = [
[4*I, 0*I],
[1*(-I), 1*I]
]
This should generate the result:
A = [
[4, 0, 0, 0],
[0, 4, 0, 0],
[-1, 0, 1, 0],
[0, -1, 0, 1]
]
Looks like you want the Kronecker product.
In [585]: np.kron(np.ones((2,2),int), np.eye(2,dtype=int))
Out[585]:
array([[1, 0, 1, 0],
[0, 1, 0, 1],
[1, 0, 1, 0],
[0, 1, 0, 1]])
You were try to make the array with repeated uses of the eye:
In [590]: np.array([I,I,I])
Out[590]:
array([[[1, 0],
[0, 1]],
[[1, 0],
[0, 1]],
[[1, 0],
[0, 1]]])
This is a (3,2,2), that's joining the eye on a new leading axis.
It is possible to transpose/reshape the (2,2,2,2) produced by np.array([[I,I],[I,I]]), but I'll you with the kron.

Changing the order of a matrix in numpy

I have a matrix
test = np.array([[0,1,0,0],[1,0,1,1],[0,1,0,1],[0,1,1,0]])
How do I reorder the columns so that they are like this matrix? (Basically the last row becomes the first row in reverse order and so on...)
np.array([[0,1,1,0],[1,0,1,0],[1,1,0,1],[0,0,1,0]])
Just reverse both axis
test[::-1,::-1]
array([[0, 1, 1, 0],
[1, 0, 1, 0],
[1, 1, 0, 1],
[0, 0, 1, 0]])
Update (ahh... Okay, I think I understand now.)
You can use negative steps for both the inner and outer steps.
test[::-1, ::-1]
Output:
array([[0, 1, 1, 0],
[1, 0, 1, 0],
[1, 1, 0, 1],
[0, 0, 1, 0]])
To reverse both the row and column you can use the np.flip, in your case:
test = np.array([[0,1,0,0],[1,0,1,1],[0,1,0,1],[0,1,1,0]])
reversed = np.flip(test, axis=[0,1])

numpy roll along a single axis

I have a numpy array with binary values that I need to change in the following way: The value of every element must be shifted one column to the left but only within the same row. As an example, I have the following array:
>>> arr = np.array([[0,0,1,0],[1,0,0,0],[0,0,1,1]])
>>> arr
array([[0, 0, 1, 0],
[1, 0, 0, 0],
[0, 0, 1, 1]])
And it needs to be transformed to:
>>> arr
array([[0, 1, 0, 0],
[0, 0, 0, 1],
[0, 1, 1, 0]])
I know that np.roll(arr,-1) would roll the values one cell to the left, but it doesn't seem to be able to roll them within the rows they belong to (i.e. the element on cell [1,0] goes to [0,3] instead of the desired [1,3]. Is there a way of doing this?
Thanks in advance.
roll accepts an axis parameter:
np.roll(arr,-1, axis=1)
array([[0, 1, 0, 0],
[0, 0, 0, 1],
[0, 1, 1, 0]])

Finding largest indices of non-zero elements along each axis

I have a 3d numpy array. I'd like to find the largest x, y and z co-ordinates of non-zero element elements along each of the three axes of the array. How can I do that?
So for the example below x=1, y=2, z=1
array([[[1, 1, 0],
[1, 1, 0],
[0, 0, 0]],
[[0, 0, 0],
[1, 0, 0],
[1, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]])
Get the indices of non-zero elements with np.nonzero and stack them up in columns with np.column_stack and finally find the max along the columns with .max(0). The implementation would look something like this -
np.column_stack((np.nonzero(A))).max(0)
Looks like there is a built-in function np.argwhere for getting indices of all non-zero elements stacked in a 2D array. Thus, you can simply do -
np.argwhere(A).max(0)
Sample run -
In [50]: A
Out[50]:
array([[[1, 1, 0],
[1, 1, 0],
[0, 0, 0]],
[[0, 0, 0],
[1, 0, 0],
[1, 0, 0]],
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]])
In [51]: np.column_stack((np.nonzero(A))).max(0)
Out[51]: array([1, 2, 1])
In [52]: np.argwhere(A).max(0)
Out[52]: array([1, 2, 1])
Done using numpy.nonzero
>>> tuple(coords.max() for coords in numpy.nonzero(A))
(1, 2, 1)

Updating by index in an multi-dimensional numpy array

I am using numpy to tally a lot of values across many large arrays, and keep track of which positions the maximum values appear in.
In particular, imagine I have a 'counts' array:
data = numpy.array([[ 5, 10, 3],
[ 6, 9, 12],
[13, 3, 9],
[ 9, 3, 1],
...
])
counts = numpy.zeros(data.shape, dtype=numpy.int)
data is going to change a lot, but I want 'counts' to reflect the number of times the max has appeared in each position:
max_value_indices = numpy.argmax(data, axis=1)
# this is now [1, 2, 0, 0, ...] representing the positions of 10, 12, 13 and 9, respectively.
From what I understand of broadcasting in numpy, I should be able to say:
counts[max_value_indices] += 1
What I expect is the array to be updated:
[[0, 1, 0],
[0, 0, 1],
[1, 0, 0],
[1, 0, 0],
...
]
But instead this increments ALL the values in counts giving me:
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
...
]
I also though perhaps if I transformed max_value_indices to a 100x1 array, it might work:
counts[max_value_indices[:,numpy.newaxis]] += 1
but this has effect of updating just the elements in positions 0, 1, and 2:
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[0, 0, 0],
...
]
I'm also happy to turn the indices array into an array of 0's and 1's, and then add it to the counts array each time, but I'm not sure how to construct that.
You could use so-called advanced integer indexing (aka Multidimensional list-of-locations indexing):
In [24]: counts[np.arange(data.shape[0]),
np.argmax(data, axis=1)] += 1
In [25]: counts
Out[25]:
array([[0, 1, 0],
[0, 0, 1],
[1, 0, 0],
[1, 0, 0]])
The first array, np.arange(data.shape[0]) specifies the row. The second array, np.argmax(data, axis=1) specifies the column.

Categories

Resources