Perform operation in NumPy array except for some values - python

Is there a simple way to lock/freeze an element within a Numpy Array. I would like to do several operations over a Numpy Array in python while keeping some specific values as they are originally.
for example,
if a have a Numpy Array a ;
[[ 1 3 4 5],
[6 7 8 0],
[9 10 11 2]]
and another Numpy Array b ;
[[2 0 4 10],
[11 5 12 3],
[6 8 7 9]]
and c = a+b but keeping the original values of 3, 8 and 2 in a.
My arrays are quite big and I would like a solution where I don't have to use a for loop, an if statement or something similar.

You can use np.isin to build a mask, and then np.where to populate from either a or a+b depending on on the result:
m = np.isin(a, [3,8,2])
c = np.where(m, a, a+b)
Or as #hpaulj suggests, you could also use where and out in np.add, which would modify a in-place:
np.add(a, b, where=~np.isin(a,[3,8,2]), out=a)
array([[ 3, 3, 8, 15],
[17, 12, 8, 3],
[15, 18, 18, 2]])

Related

How to access array from vectors by time index

Let's say I have four different vectors from a measurement, where each index corresponds to a certain time. Meaning that the values "1, 4, 7, 10" or also "2, 5, 8, 11" of the following example belong together. I now want to create a matrix, which allows to be accessed by time index. With time index I mean 0, 1 or 2 in the following example. I hope the following examples makes it a bit clearer.
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.array([7, 8, 9])
d = np.array([10, 11, 12])
mat = np.array([[a, b],
[c, d]])
mat[0] then returns
[[1 2 3]
[4 5 6]]
but I want that it returns is
[[1 4]
[7 10]]
How can I achieve this?
Since mat is a 3-dim array (and not a matrix), you should use:
print(mat[:,:,0])

Using numpy.ones as indices of an array

I would like to translate a matlab code into a python one. The matlab code is equivalent to the following toy example:
a = [1 2 3; 4 5 6; 7 8 9]
b = a(:, ones(1,3))
It returns
a =
1 2 3
4 5 6
7 8 9
b =
1 1 1
4 4 4
7 7 7
I tried to translate it like this:
from numpy import array
from numpy import ones
a = array([ [1,2,3], [4,5,6], [7,8,9] ])
b = a[:][ones((1,3))]
but it returns the following error message:
Traceback (most recent call last):
File "example_slice.py", line 6, in
b =a[:, ones((1,3))]
IndexError: arrays used as indices must be of integer (or boolean) type
EDIT: maybe ones should be replaced by zeros in this particular case but it is not the problem here. The question deals with the problem of giving a list containing the same index many times to the array a in order to get the same array b as the one computed with Matlab.
The MATLAB code can also be written (more idiomatically and more clearly) as:
b = repmat(a(:,1),1,3);
In NumPy you'd write:
b = np.tile(a[:,None,0],(1,3))
(Note the None needed to preserve the orientation of the vector extracted).
You could use list comprehension with np.full() to create arrays of certain values.
import numpy as np
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
b = np.array([np.full(len(i), i[0]) for i in a])
print(b)
Output:
[[1 1 1]
[4 4 4]
[7 7 7]]
In [568]: a = np.array([ [1,2,3], [4,5,6], [7,8,9] ])
In [569]: a[:,0]
Out[569]: array([1, 4, 7])
In [570]: a[:,[0,0,0]]
Out[570]:
array([[1, 1, 1],
[4, 4, 4],
[7, 7, 7]])
In [571]: a[:, np.zeros(3, dtype=int)] # int dtype to avoid your error
Out[571]:
array([[1, 1, 1],
[4, 4, 4],
[7, 7, 7]])
====
In [572]: np.zeros(3)
Out[572]: array([0., 0., 0.])
In [573]: np.zeros(3, int)
Out[573]: array([0, 0, 0])
Earlier numpy versions allowed float indices, but newer ones have tightened the requirement.

How to update all the values of a numpy array using values from another array

*Question edited/updated to add an example
Hi all! I have this a np.array. Based on the reference values of it, I want to update array b, which is my matrix. The "1st column" of a represents a code and the "2nd column" is my reference value. The matrix is populated with codes and I must replace them. See below the example.
import numpy as np
a = np.asarray([[0, 11], [1, 22], [2, 33]])
b = np.asarray([[0, 14, 12, 2], [1, 1, 7, 0], [0, 0,3,5], [1, 2, 2, 6]])
In other words: I want to replace the 0, 1, 2 values in "b" by 11, 22, 33, respectively.
Which is the best way to do that, considering that my real a array has +- 50 codes and my real b matrices have a shape of (850,850).
Thanks in advance!
If I understand the question correctly, this example should show what you're asking for?
Assuming a is the matrix as you've listed above, and b is the list you want to write to
import numpy as np
a = np.asarray([[0, 10], [2, 30], [1, 40]])
b = np.zeros(3)
b[a[:, 0]] = a[:, 1]
where the [:, 0] is the index to be changed, and [:, 1] is what to populate it with
If codes are not too long integers, You just have to build the correct lookup table :
lut = np.arange(b.max()+1)
k,v = a.T
lut[k] = v
For :
>>> b
[[ 0 14 12 2]
[ 1 1 7 0]
[ 0 0 3 5]
[ 1 2 2 6]]
>>> lut[b]
[[11 14 12 33]
[22 22 7 11]
[11 11 3 5]
[22 33 33 6]]
undefined codes are mapped to themselves,code=value.

How to specify columns when using repeated indices with numpy [for use with np.add.at()]

I'm trying to apply an addition operator to an array where I want repeated indices to indicate repeated addition operations. From a Python Data Science Book (https://jakevdp.github.io/PythonDataScienceHandbook/02.07-fancy-indexing.html), it seems that this is possible using np.add.at(original matrix, indices, thing to add), but I can't figure out how to specify the indices to operate on columns, not rows.
e.g. Dummy Example
# Create Array
A = np.arange(12)
A = A.reshape(4,3)
print(A)
gives
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
and
# Create columns to add to A (in reality, all values won't be the same)
B = np.ones_like(A[:, [0,0]])
print(adder)
gives
[[1 1]
[1 1]
[1 1]
[1 1]]
I want to perform the operation A[:, [0, 0]] += B but using the system where repeated indices indicate repeated operations (so in this case, both columns of B gets added to column 0). The result should thus be:
[[ 2 1 2]
[ 5 4 5]
[ 7 7 8]
[ 11 10 11]]
This can be done using np.add.at(A, I, B) I believe, but how do I specify the indices I to correspond to [:, [0,0]] as this gives a syntax error (it seems that the indices matrix can't contain the : character?).
Thanks
In [12]: A = np.arange(12).reshape(4,3)
In [13]: np.add.at(A, (slice(None), [0,0]), 1)
In [14]: A
Out[14]:
array([[ 2, 1, 2],
[ 5, 4, 5],
[ 8, 7, 8],
[11, 10, 11]])
This could also be written with s_ as
np.add.at(A, np.s_[:, [0,0]], 1)
s_ is a class object that lets us using indexing notation to create the necessary tuple. In an indexing context Python interpreter converts the : into a slice object.
In [19]: np.s_[:, [0,0]]
Out[19]: (slice(None, None, None), [0, 0])

Trouble vectorizing code

I'm having a hard time on doing this. I have two m x n matrices (A and B) and I need to multiply every column of A by the rows in B, to generate a m x (n*n) matrix. I guess I wasn't very clear in the explanation so I'll post an example:
A =
[1 2
3 4]
B =
[5 6
7 8]
I wish to have:
[[5 6] [10 12]
[21 24] [28 32]]
I was able to do it using for loops but I want to avoid for as much as possible. Also using numpy to all this and all data is stored as np.array.
Maybe:
>>> A = np.array([[1,2],[3,4]])
>>> B = np.array([[5,6],[7,8]])
>>> (A * B[None, :].T).T
array([[[ 5, 6],
[21, 24]],
[[10, 12],
[28, 32]]])
where we use None to add an extra dimension to B, and a few transpositions to get the alignment right.
If I understand you right, you want basic ( m * n ) multiplication right? Use numpy.dot():
>>> a = [[1, 0], [0, 1]]
>>> b = [[4, 1], [2, 2]]
>>> np.dot(a, b)
array([[4, 1],
[2, 2]])

Categories

Resources