How do I select rows in an input numpy array and store operation results in corresponding row in an output array?

Viewed 80

This is a rough visualization of what I want to achieve, but also read the text.

So I have a bunch of numpy arrays stored in the manner below. I'm using 2's in 'other' only for simplicity's sake in this post.

matrices['in'] = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
matrices['other'] = np.array([[2, 2, 2], [2, 2, 2], [2, 2, 2]])
matrices['out'] = np.zeros((n, n), dtype=np.int)

I.e.

>>> matrices['in']
[[1 2 3]
 [4 5 6]
 [7 8 9]]

>>> matrices['other']
[[2 2 2]
 [2 2 2]
 [2 2 2]]

>>> matrices['out']
[[0 0 0]
 [0 0 0]
 [0 0 0]]

I wish to do some kind of operation per row but I wish to have control over which rows are included in my overall calculations. So I made another array:

included = [True] * n
matrices['included'] = np.array(included)
matrices['included'].itemset(1, False)

>>> matrices['included']
[ True False  True]

And it seems to work as intended.

mask = matrices['included']
>>> matrices['in'][mask]
[[1 2 3]
 [7 8 9]]

However. As you may have noticed above, I use a predefined output in matrices['out'] as the operations are done more frequently than the size of the array is changing, so I naturally do not want to recreate a new array object every time I do new calculations.

Thus my operations looks something like this:

np.multiply(matrices['in'], matrices['other'], out=matrices['out'])

or in the case of using numexpr:

numexpr.evaluate("m_in * m_other",
    local_dict={
        'm_in': matrices['in'],
        'm_other': matrices['other']
    },
    out=matrices['out'])

These works fine as above, but the issue I have is that I can't figure out how to get this to work with the mask; selecting rows via matrices['included'] and have them stored in corresponding row in my output matrix.

When I do either of:

np.multiply(matrices['in'][mask], matrices['other'][mask], out=matrices['out'][mask])

or

numexpr.evaluate("m_in * m_other",
    local_dict={
        'm_in': matrices['in'][mask],
        'm_other': matrices['other'][mask]
    },
    out=matrices['out'][mask])

nothing happens, i.e. it results in:

>>> matrices['out']
[[0 0 0]
 [0 0 0]
 [0 0 0]]

And using [mask, ...] or [mask, :] results in the same thing.

The output I would want in this case is:

[[2 4 6]
 [0 0 0]
 [14 16 18]]
1 Answers

Numpy.multiply has a where keyword that allows you to include a mask for the operation. This will apply the operation in the specified locations and leave the output array untouched everywhere else.

The example below should give you the behavior you are looking for:

import numpy as np
A=np.array([[1,2,3],[4,5,6],[7,8,9]])
B=2*np.ones(3,dtype=int)
C=np.zeros((3,3),dtype=int)
mask=np.transpose([[True,False,True],])

np.multiply(A,B,out=C,where=mask)
print(C)

I haven't tried your example to confirm this, but I believe when you applied the mask to the out array, you created a new array where the output actually was sent.

Related