Let A,C and B be numpy arrays with the same number of rows.
I want to update 0th element of A[0], 2nd element of A[1] etc. That is, update B[i]th element of A[i] to C[i]
import numpy as np
A = np.array([[1,2,3],[3,4,5],[5,6,7],[0,8,9],[3,7,5]])
B = np.array([0,2,1,2,0])
C = np.array([8,9,6,5,4])
for i in range(5):
A[i, B[i]] = C[i]
print ("FOR", A)
A = np.array([[1,2,3],[3,4,5],[5,6,7],[0,8,9],[3,7,5]])
A[:,B[:]] = C[:]
print ("Vectorized, A", A)
Output:
FOR [[8 2 3]
[3 4 9]
[5 6 7]
[0 8 5]
[4 7 5]]
Vectorized, A [[4 6 5]
[4 6 5]
[4 6 5]
[4 6 5]
[4 6 5]]
The for loop and vectorization gave different results.
I am unsure how to vectorize this for loop using Numpy.
The reason that your approach doesn't work is that you're passing the whole B as the column index and replace them with C instead you need to specify both row index and column index. Since you just want to change the first 4 rows you can simply use np.arange(4) to select the rows B[:4] the columns and C[:4] the replacement items.
In [26]: A[np.arange(4),B[:4]] = C[:4]
In [27]: A
Out[27]:
array([[8, 2, 3],
[3, 4, 9],
[5, 6, 7],
[0, 8, 5],
[3, 7, 5]])
Note that if you wanna update the whole array, as mentioned in comments by #Warren you can use following approach:
A[np.arange(A.shape[0]), B] = C
Related
I have 2 numpy arrays, one 2D and the other 1D, for example like this:
import numpy as np
a = np.array(
[
[1, 2],
[3, 4],
[5, 6]
]
)
b = np.array(
[7, 8, 9, 10]
)
I want to get all possible combinations of the elements in a and b, treating a like a 1D array, so that it leaves the rows in a intact, but also joins the rows in a with the items in b. It would look something like this:
>>> combine1d(a, b)
[ [1 2 7] [1 2 8] [1 2 9] [1 2 10]
[3 4 7] [3 4 8] [3 4 9] [3 4 10]
[5 6 7] [5 6 8] [5 6 9] [5 6 10] ]
I know that there are slow solutions for this (like a for loop), but I need a fast solution to this as I am working with datasets with millions of integers.
Any ideas?
This is one of those cases where it's easier to build a higher dimensional object, and then fix the axes when you're done. The first two dimensions are the length of b and the length of a. The third dimension is the number of elements in each row of a plus 1. We can then use broadcasting to fill in this array.
x, y = a.shape
z, = b.shape
result = np.empty((z, x, y + 1))
result[...,:y] = a
result[...,y] = b[:,None]
At this point, to get the exact answer you asked for, you'll need to swap the first two axes, and then merge those two axes into a single axis.
result.swapaxes(0, 1).reshape(-1, y + 1)
An hour later. . . .
I realized by being a little bit more clever, I didn't need to swap axes. This also has the nice benefit that the result is a contiguous array.
def convert1d(a, b):
x, y = a.shape
z, = b.shape
result = np.empty((x, z, y + 1))
result[...,:y] = a[:,None,:]
result[...,y] = b
return result.reshape(-1, y + 1)
this is very "scotch tape" solution:
import numpy as np
a = np.array(
[
[1, 2],
[3, 4],
[5, 6]
]
)
b = np.array(
[7, 8, 9, 10]
)
z = []
for x in b:
for y in a:
z.append(np.append(y, x))
np.array(z).reshape(3, 4, 3)
You need to use np.c_ to attach to join two dataframe. I also used np.full to generate a column of second array (b). The result are like what follows:
result = [np.c_[a, np.full((a.shape[0],1), x)] for x in b]
result
Output
[array([[1, 2, 7],
[3, 4, 7],
[5, 6, 7]]),
array([[1, 2, 8],
[3, 4, 8],
[5, 6, 8]]),
array([[1, 2, 9],
[3, 4, 9],
[5, 6, 9]]),
array([[ 1, 2, 10],
[ 3, 4, 10],
[ 5, 6, 10]])]
The output might be kind of messy. But it's exactly like what you mentioned as your desired output. To make sure, you cun run below to see what comes from the first element in the result array:
print(result[0])
Output
array([[1, 2, 7],
[3, 4, 7],
[5, 6, 7]])
When using matrix in numpy, I want to change the value of one element in a matrix using the index, but the result I got is strange.
How can I change one value in indexing method?
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
mat1 = np.mat(arr)
mat1[1][0] = 3
print(arr)
[[1 2 3 4]
[3 3 3 3]]
Do the following change:
mat1[1][0] = 3 -> mat1[1,0] = 3
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]])
If I have two arrays in python:
Array 1 =
[[1 2]
[3 4]]
Array 2 =
[[5 6]]
How can I use .append or .extend to create an array, such that:
Array 3:
[[1 2 5 6]
[3 4 5 6]]
Assuming you have numpy arrays, you can broadcast the second array to the shape of the first, and concatenate along the second axis with:
array1 = np.array([[1,2],[3,4]])
array2 = np.array([5,6])
np.c_[array1, np.broadcast_to(array2, array1.shape)]
array([[1, 2, 5, 6],
[3, 4, 5, 6]])
You can append the second array to the first one using np.append with axis=1.
array1 = np.array([[1,2],[3,4]])
array2 = np.array([[5,6]])
Make sure the shape match while appending, use broadcast_to to help with this
array3 = np.append(array1, np.broadcast_to(array2,array1.shape), axis=1)
[[1 2 5 6]
[3 4 5 6]]
This question already has answers here:
Indexing one array by another in numpy
(4 answers)
Closed 6 years ago.
consider the array a
np.random.seed([3,1415])
a = np.random.choice(np.arange(8), (2, 4), False)
print(a)
[[7 1 4 5]
[6 2 3 0]]
I'll create another array b that holds the results of np.argsort along each row.
b = a.argsort(1)
print(b)
[[1 2 3 0]
[3 1 2 0]]
I want to produce the sorted version of a by doing an appropriate slice of a with b. It should look like this
idx0 = np.arange(a.shape[0]).repeat(a.shape[1])
print(a[idx0, b.ravel()].reshape(a.shape))
[[1 4 5 7]
[0 2 3 6]]
question
what is the appropriate way to slice an 2 x 4 array with another 2 x 4 array in the fashion described above?
Advanced-indexing for the help -
a[np.arange(b.shape[0])[:,None],b]
Sample run -
In [10]: a
Out[10]:
array([[7, 1, 4, 5],
[6, 2, 3, 0]])
In [11]: b
Out[11]:
array([[1, 2, 3, 0],
[3, 1, 2, 0]])
In [12]: a[np.arange(b.shape[0])[:,None],b]
Out[12]:
array([[1, 4, 5, 7],
[0, 2, 3, 6]])