Slicing a 2D numpy array in python - python

What's wrong with the code below?
arr=numpy.empty((2,2))
arr[0:,0:]=1
print(arr[1:,1:])
arr=([ [1, 2, 3], [ 4, 5, 6], [ 7, 8, 9] ])
print(arr[1:2, 1])
I am getting the following error and not able to slice the array( fifth line). Please help me with this.
TypeError: list indices must be integers, not tuple.

You rebind the name arr to point to a Python list in your fourth line, and so your question title doesn't quite fit: you're not slicing a 2d numpy array. lists can't be sliced the way that numpy arrays can. Compare:
>>> arr= numpy.array([ [1, 2, 3], [ 4, 5, 6], [ 7, 8, 9] ])
>>> arr
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> arr[1:2, 1]
array([5])
but
>>> arr.tolist()
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> arr.tolist()[1:2, 1]
Traceback (most recent call last):
File "<ipython-input-23-4a441cf2eaa9>", line 1, in <module>
arr.tolist()[1:2, 1]
TypeError: list indices must be integers, not tuple

arr=([ [1, 2, 3], [ 4, 5, 6], [ 7, 8, 9] ]) is a python list,not a numpy array.
You reassign arr with arr=([ [1, 2, 3], [ 4, 5, 6], [ 7, 8, 9] ]) to a list.
Make it a numpy array:
In [37]: arr = numpy.array([ [1, 2, 3], [ 4, 5, 6], [ 7, 8, 9] ])
In [38]: arr
Out[38]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [39]: (arr[1:2, 1])
Out[39]: array([5])

Related

numpy array slicing produces an error indexing arrays could not be broadcast together

I have an np.array :
a = np.array([x for x in range(10) for y in range(10)]).reshape(10, 10)
I want to get the 3rd and the 6th rows columns 4,7,10 - marked in green.
I tried:
a[[2,5]] # gives me the rows I want
a[[2,5], [3,6,10]] # produces an an error
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (3,)
In the end the result should look like:
[[2,2,2],
[5,5,5]]
Where is my mistake?
the first index list must the (2,1) shape (or list equivalent):
In [31]: a[[[2], [5]], [3, 6, 9]]
Out[31]:
array([[2, 2, 2],
[5, 5, 5]])
Do you understand what the error message means by broadcasting?
For simple addition, a (2,1) array broadcasts with a (3,) to produce a (2,3) result:
In [32]: I, J = np.array((2, 5)), np.array((3, 6, 9))
In [33]: I, J
Out[33]: (array([2, 5]), array([3, 6, 9]))
In [34]: I + J
Traceback (most recent call last):
Input In [34] in <module>
I + J
ValueError: operands could not be broadcast together with shapes (2,) (3,)
In [35]: I[:, None] + J
Out[35]:
array([[ 5, 8, 11],
[ 8, 11, 14]])
The same idea applies to indexing with several arrays.
Your a can be created with the same logic:
In [38]: np.arange(10)[:, None] + np.zeros(10,int)
Out[38]:
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6],
[7, 7, 7, 7, 7, 7, 7, 7, 7, 7],
[8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]])
With 2 arrays (lists) of matching size, the effect is to select a "diagonal", or 1d array of values (rather than the block that you were trying to get):
In [39]: a[[2, 3], [5, 6]]
Out[39]: array([2, 3])
In [40]: a[2, 5], a[3, 6]
Out[40]: (2, 3)
I believe this link will explain everything since the question is the same and was given great answer:
Selecting specific rows and columns from NumPy array

Appending to numpy array column wise

I have an array
a = np.array([
[1, 2, 3],
[2, 3, 4]
])
and 3 more column wise arrays
b=np.array([[1],
[2],
[3]])
c=np.array([[5],
[6],
[7]])
d=np.array([[9],
[10],
[11]])
I want to concatenate my array such the column wise arrays are appended to the original array "a" like this
a = np.array([
[1, 2, 3],
[2, 3, 4],
[1, 5, 9],
[2, 6, 10],
[3, 7, 11],
])
def st():
a = np.array([[1, 2, 3],[2, 3, 4]])
b=np.array([[1],[2],[3]])
c=np.array([[5],[6],[7]])
d=np.array([[9],[10],[11]])
return np.vstack([a, np.hstack([b,c,d])])
Results:
>>> st()
array([[ 1, 2, 3],
[ 2, 3, 4],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])

numpy select values based on list of indices. Process batch at once [duplicate]

Suppose I have a matrix A with some arbitrary values:
array([[ 2, 4, 5, 3],
[ 1, 6, 8, 9],
[ 8, 7, 0, 2]])
And a matrix B which contains indices of elements in A:
array([[0, 0, 1, 2],
[0, 3, 2, 1],
[3, 2, 1, 0]])
How do I select values from A pointed by B, i.e.:
A[B] = [[2, 2, 4, 5],
[1, 9, 8, 6],
[2, 0, 7, 8]]
EDIT: np.take_along_axis is a builtin function for this use case implemented since numpy 1.15. See #hpaulj 's answer below for how to use it.
You can use NumPy's advanced indexing -
A[np.arange(A.shape[0])[:,None],B]
One can also use linear indexing -
m,n = A.shape
out = np.take(A,B + n*np.arange(m)[:,None])
Sample run -
In [40]: A
Out[40]:
array([[2, 4, 5, 3],
[1, 6, 8, 9],
[8, 7, 0, 2]])
In [41]: B
Out[41]:
array([[0, 0, 1, 2],
[0, 3, 2, 1],
[3, 2, 1, 0]])
In [42]: A[np.arange(A.shape[0])[:,None],B]
Out[42]:
array([[2, 2, 4, 5],
[1, 9, 8, 6],
[2, 0, 7, 8]])
In [43]: m,n = A.shape
In [44]: np.take(A,B + n*np.arange(m)[:,None])
Out[44]:
array([[2, 2, 4, 5],
[1, 9, 8, 6],
[2, 0, 7, 8]])
More recent versions have added a take_along_axis function that does the job:
A = np.array([[ 2, 4, 5, 3],
[ 1, 6, 8, 9],
[ 8, 7, 0, 2]])
B = np.array([[0, 0, 1, 2],
[0, 3, 2, 1],
[3, 2, 1, 0]])
np.take_along_axis(A, B, 1)
Out[]:
array([[2, 2, 4, 5],
[1, 9, 8, 6],
[2, 0, 7, 8]])
There's also a put_along_axis.
I know this is an old question, but another way of doing it using indices is:
A[np.indices(B.shape)[0], B]
output:
[[2 2 4 5]
[1 9 8 6]
[2 0 7 8]]
Following is the solution using for loop:
outlist = []
for i in range(len(B)):
lst = []
for j in range(len(B[i])):
lst.append(A[i][B[i][j]])
outlist.append(lst)
outarray = np.asarray(outlist)
print(outarray)
Above can also be written in more succinct list comprehension form:
outlist = [ [A[i][B[i][j]] for j in range(len(B[i]))]
for i in range(len(B)) ]
outarray = np.asarray(outlist)
print(outarray)
Output:
[[2 2 4 5]
[1 9 8 6]
[2 0 7 8]]

Sum each row of a numpy array with all rows of second numpy array (python)

I would like to know if there is any fast way to sum each row of a first array with all rows of a second array. In this case both arrays have the same number of colulmns. For instance if array1.shape = (n,c) and array2.shape = (m,c), the resulting array would be an array3.shape = ((n*m), c)
Look at the example below:
array1 = np.array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
array2 = np.array([[0, 1, 2],
[3, 4, 5]])
The result would be:
array3 = np.array([[0, 2, 4],
[3, 5, 7]
[3, 5, 7]
[6, 8, 10]
[6, 8, 10]
[9, 11, 13]])
The only way I see I can do this is to repeat each row of one of the arrays the number of rows of the other array. For instance, by doing np.repeat(array1, len(array2), axis=0) and then sum this array with array2. This is not very practical however if the number of rows is too big. The other way would be with a for loop but this is too slow.
Any other better way to do it..?
Thanks in advance.
Extend array1 to 3D so that it becomes broadcastable against 2D array2 and then perform broadcasted addition and a final reshape is needed for desired output -
In [30]: (array1[:,None,:] + array2).reshape(-1,array1.shape[1])
Out[30]:
array([[ 0, 2, 4],
[ 3, 5, 7],
[ 3, 5, 7],
[ 6, 8, 10],
[ 6, 8, 10],
[ 9, 11, 13]])
You could try the following inline code if you haven't already. This is the simplest and probably also the quickest on a single thread.
>>> import numpy as np
>>> array1 = np.array([[0, 1, 2],
... [3, 4, 5],
... [6, 7, 8]])
>>>
>>> array2 = np.array([[0, 1, 2],
... [3, 4, 5]])
>>> array3 = np.array([i+j for i in array1 for j in array2])
>>> array3
array([[ 0, 2, 4],
[ 3, 5, 7],
[ 3, 5, 7],
[ 6, 8, 10],
[ 6, 8, 10],
[ 9, 11, 13]])
>>>
If you are looking for speed up by treading, you could consider using CUDA or multithreading. This suggestion goes a bit out of scope of your question but gives you an idea of what can be done to speed up matrix operations.

Insert 1D NumPy array as column in existing 2D array

I have a 2D NumPy array:
>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> a
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
and a 1D array:
>>> b = np.arange(3)
>>> b
array([0, 1, 2])
Is there an elegant way to insert b into a as a new first column?
So that:
>>> a
array([[0, 1, 2, 3],
[1, 4, 5, 6],
[2, 7, 8, 9]])
You could use column_stack()
In [256]: np.column_stack((b, a))
Out[256]:
array([[0, 1, 2, 3],
[1, 4, 5, 6],
[2, 7, 8, 9]])

Categories

Resources