Fancy Indexing

노정훈·2023년 7월 15일
0

Numpy

목록 보기
8/10

Exploring Fancy Indexing

# In[1]
rng=np.random.default_rng(seed=1701)
x=rng.integers(100,size=10)
print(rng)
print(x)
# Out[1]
Generator(PCG64)
[90 40  9 30 80 67 39 15 33 79]
  • If we want to access three different elements. We could do it like this
# In[2]
[x[3],x[7],x[2]]
# Out[2]
[30, 15, 9]
  • Alternatively, we can pass a single list or array of indices to obtain the same result.
# In[3]
ind=[3,7,4]
x[ind]
# Out[3]
array([30, 15, 80])
  • When using arrays of indices, the shape of the result reflects the shape of the index arrays rather than the shape of the array being indexed.
# In[4]
ind=np.array([[3,7],[4,5]])
x[ind]
# Out[4]
array([[30, 15],
       [80, 67]])
  • Fancy indexing also works in multiple dimensions.
# In[5]
X=np.arange(12).reshape((3,4))
X
# Out[5]
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

# In[6]
row=np.array([0,1,2])
col=np.array([2,1,3])
X[row,col]
# Out[6]
array([ 2,  5, 11])
  • The first value in the result is X[0,2], the second is X[1,1], and the third is X[2,3]
  • The pairing of indices in fancy indexing follows all the broadcasting rules.
# In[7]
X[row[:,np.newaxis],col]
# Out[7]
array([[ 2,  1,  3],
       [ 6,  5,  7],
       [10,  9, 11]])
  • Fancy indexing that the return value reflects the broadcasted shape of the indices.

Combined Indexing

  • We can combine fancy and simple indices
# In[8]
X
# Out[8]
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

# In[9]
X[2,[2,0,1]]
# Out[9]
array([10,  8,  9])
  • We can also combine fancy indexing and slicing
# In[10]
X[1:,[2,0,1]]
# Out[10]
array([[ 6,  4,  5],
       [10,  8,  9]])
  • We can combine fancy indexing with masking
# In[11]
mask=np.array([1,0,1,0],dtype=bool)
X[row[:,np.newaxis],mask]
# Out[11]
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])

Modifying Values with Fancy Indexing

# In[12]
x=np.arange(10)
i=np.array([2,1,8,4])
x[i]=99
print(x)
# Out[12]
[ 0 99 99  3 99  5  6  7 99  9]

# In[13]
x[i]-=10
print(x)
# Out[13]
[ 0 89 89  3 89  5  6  7 89  9]
  • You have to notice that repeated indices with these operations can cause some potentially unexpected results.
# In[14]
x=np.zeros(10)
x[[0,0]]=[4,6]
print(x)
# Out[14]
[6. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
  • This operation first assign x[0]=4 , followed by x[0]=6. So, x[0] contains the value 6
# In[15]
i=[2,3,3,4,4,4]
x[i]+=1
x
# Out[15]
array([6., 0., 1., 1., 1., 0., 0., 0., 0., 0.])
  • x[i]+=1 is meant as a shorthand of x[i]=x[i]+1.
  • x[i]+1 is evaluated, and then the result is assigned to the indices in x
  • With this in mind, it is not the augmentation that happens multiple times, but the assignment, which leads to the rather nonintuitive results.
  • So, if you want the other behavior where the operation is repeated, you can use the at method of ufuncs.
# In[16]
x=np.zeros(10)
np.add.at(x,i,1)
print(x)
# Out[16]
[0. 0. 1. 2. 3. 0. 0. 0. 0. 0.]
  • at method does an in-place application of the given operator at the specified indices (here,i) with the specified value (here,i)
profile
노정훈

0개의 댓글