Difference between x[:] and x[...] in Numpy - numpy

I am confused about the difference between x[:] and x[...] in Numpy.
For example, I have this 2-d array
[[4, 1, 9],
[5, 2, 0]]
When I tried to print out x[:] and x[...], they both gave me the same output:
[[4, 1, 9],
[5, 2, 0]]
However, when I tried to broadcast it by adding one dimension
print(np.broadcast_to(x[:,None],(2,3,3)))
print(np.broadcast_to(x[...,None],(2,3,3)))
They gave me different results.
[[[4 1 9]
[4 1 9]
[4 1 9]]
[[5 2 0]
[5 2 0]
[5 2 0]]]
[[[4 4 4]
[1 1 1]
[9 9 9]]
[[5 5 5]
[2 2 2]
[0 0 0]]]
I am trying to figure out the difference but cannot.

In [91]: x = np.array([[4, 1, 9],
...: [5, 2, 0]])
In [92]: x
Out[92]:
array([[4, 1, 9],
[5, 2, 0]])
These just make a whole slice, a view of the original:
In [93]: x[:]
Out[93]:
array([[4, 1, 9],
[5, 2, 0]])
In [94]: x[...]
Out[94]:
array([[4, 1, 9],
[5, 2, 0]])
In [95]: x[:,:]
Out[95]:
array([[4, 1, 9],
[5, 2, 0]])
Trailing : are added as needed, but you can't supply more than the number of dimensions:
In [96]: x[:,:,:]
Traceback (most recent call last):
File "<ipython-input-96-9d8949edcb06>", line 1, in <module>
x[:,:,:]
IndexError: too many indices for array: array is 2-dimensional, but 3 were indexed
None adds a dimension:
In [97]: x[:,None].shape # after the first
Out[97]: (2, 1, 3)
In [98]: x[...,None].shape # at the end
Out[98]: (2, 3, 1)
In [99]: x[:,:,None].shape # after the 2nd
Out[99]: (2, 3, 1)
In [100]: x[:,None,:].shape # same as 97
Out[100]: (2, 1, 3)
In [101]: x[None].shape # same as [None,:,:] [None,...]
Out[101]: (1, 2, 3)
with a scalar index
In [102]: x[1,:] # same as x[1], x[1,...]
Out[102]: array([5, 2, 0])
In [103]: x[...,1] # same as x[:,1]
Out[103]: array([1, 2])

Related

Usage of Numpy's maximum method

I am unable to understand why the following code does not work. It is my understanding that the "maximum" method in Numpy returns an array with the element-wise maximum of any number of arrays in the argument.
import numpy as np
frame1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
frame2 = np.array([[2, 3, 4], [5, 6, 7], [9, 9, 9]])
frame3 = np.array([[3, 4, 5], [6, 7, 8], [10, 10, 10]])
result1 = np.maximum(frame2, frame3)
print(result1)
result2 = np.maximum(frame1, frame2, frame3)
print(result2)
The results are:
[[ 3 4 5]
[ 6 7 8]
[10 10 10]]
[[2 3 4]
[5 6 7]
[9 9 9]]
Is there something really trivial that I am missing? Thanks.

pytorch repeat 3rd dimension

I'm following this example on doc
In [42]: x = torch.tensor([1,2,3])
In [45]: x.repeat(4,2)
Out[45]: tensor([[1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3]])
In [46]: x.repeat(4,2).shape
Out[46]: torch.Size([4, 6])
So far, so good.
But why does repeating just 1 time on 3rd dimension expand 3rd dim to 3 (not 1)?
[On the doc]
>>> x.repeat(4, 2, 1).size()
torch.Size([4, 2, 3])
Double checking.
In [43]: x.repeat(4,2,1)
Out[43]:
tensor([[[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3]]])
Why does it behave this way?
It expands the size([3]) tensor it only once along first dim. The (4,2,1) is the number of times you want to repeat a (3,) tensor. So, the final tensor is (4,2,3), because you repeat the (3,) once over last axis, twice over second last and 4 times over the first axis.
x = torch.tensor([1, 2, 3])
x.shape
torch.Size([3])
Then,
xx = x.repeat(4,2,1)
xx.shape
torch.Size([4, 2, 3])

Delete specified column index from every row of 2d numpy array

I have a numpy array A as follows:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
and another numpy array column_indices_to_be_deleted as follows:
array([1, 0, 2])
I want to delete the element from every row of A specified by the column indices in column_indices_to_be_deleted. So, column index 1 from row 0, column index 0 from row 1 and column index 2 from row 2 in this case, to get a new array that looks like this:
array([[1, 3],
[5, 6],
[7, 8]])
What would be the simplest way of doing that?
One way with masking created with broadcatsed-comparison -
In [43]: a # input array
Out[43]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [44]: remove_idx # indices to be removed from each row
Out[44]: array([1, 0, 2])
In [45]: n = a.shape[1]
In [46]: a[remove_idx[:,None]!=np.arange(n)].reshape(-1,n-1)
Out[46]:
array([[1, 3],
[5, 6],
[7, 8]])
Another mask based approach with the mask created with array-assignment -
In [47]: mask = np.ones(a.shape,dtype=bool)
In [48]: mask[np.arange(len(remove_idx)), remove_idx] = 0
In [49]: a[mask].reshape(-1,a.shape[1]-1)
Out[49]:
array([[1, 3],
[5, 6],
[7, 8]])
Another with np.delete -
In [64]: m,n = a.shape
In [66]: np.delete(a.flat,remove_idx+n*np.arange(m)).reshape(m,-1)
Out[66]:
array([[1, 3],
[5, 6],
[7, 8]])

Indexing numpy array using another numpy array [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]]

How to simplify a numpy array indexing? [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]]