0

I am trying to get my head around numpy's fancy indexing. While trying to approach the following I am currently unable to solve the problem:

Given the following np.array t.

t = np.array([[6, 1, 8],
           [4, 3, 7],
           [9, 5, 2]])

I want to achieve the following pattern using fancy indexing

array([[8, 1, 8],
       [1, 8, 1],
       [8, 1, 8]])

With my closest approach getting to

array([[8, 1, 8],
       [8, 1, 8],
       [8, 1, 8]])

Using t[:,[2,1,2]][[0,0,0]]

how to tackle such problems?

James Z
  • 12,209
  • 10
  • 24
  • 44
Pierre
  • 1,409
  • 12
  • 15
  • 1
    What is "fancy indexing"? You mean Python's standard-since-forever list slicing syntax? Because if so, there's tons of explainers on the web about how to use that already. Including on SO, of course. E.g. https://stackoverflow.com/questions/509211/understanding-slice-notation – Mike 'Pomax' Kamermans Jun 18 '21 at 20:43
  • Thanks for pointing out. In fancy indexing (in difference to list slicing) one passes arrays as indices. – Pierre Jun 18 '21 at 20:58
  • 2
    Fancy indexing is definitely a python datascience term (albeit rarely used). Simple google search would've shown that though. No need for sass. There is a good read on it here: https://jakevdp.github.io/PythonDataScienceHandbook/02.07-fancy-indexing.html @Mike'Pomax'Kamermans – Gunner Stone Jun 18 '21 at 21:12
  • No sass, just good old genuine confusion about an unusual term I've never seen used despite having worked with numpy on more than several occasions. – Mike 'Pomax' Kamermans Jun 18 '21 at 21:57
  • @Mike'Pomax'Kamermans, that link is for `numpy`, not base Python. https://numpy.org/doc/stable/reference/arrays.indexing.html#advanced-indexing uses the name **advanced indexing**. For lists there are only 2 options - slices and individual indices. – hpaulj Jun 19 '21 at 00:42

2 Answers2

0

I found two approaches which solve the problem.

  1. Map the indices with the corresponding points to a 2d array of row and column coordinates.

    row = np.array([[0,0,0],[0,0,0],[0,0,0]])
    col = np.array([[2,1,2],[1,2,1],[2,1,2]])
    
    t[row,col]
    
    array([[8, 1, 8],
           [1, 8, 1],
           [8, 1, 8]])
    

which is the same as using

t[  [[0,0,0],[0,0,0],[0,0,0]]  ,  [[2,1,2],[1,2,1],[2,1,2]]  ]
  1. Start by creating a 1d Array including only required numbers and then cast to a 2d array, allthough is approach triggers a Future Warning: Using a non-tuple sequence for multidimensional indexing is deprecated; use arr[tuple(seq)] instead of arr[seq]. In the future this will be interpreted as an array index, arr[np.array(seq)], which will result either in an error or a different result.

      t[0,[1,2]] [[  [[1,0,1],[0,1,0],[1,0,1]]  ]]
    
      array([[8, 1, 8],
             [1, 8, 1],
             [8, 1, 8]])
    
Pierre
  • 1,409
  • 12
  • 15
0
In [198]: t = np.array([[6, 1, 8],
     ...:            [4, 3, 7],
     ...:            [9, 5, 2]])

Looks like you want to take 2 elements, and repeat them.

In [199]: t[0,[2,1]]                 # select the elements
Out[199]: array([8, 1])

Then taking advantage of how np.resize "pads" a larger array:

In [200]: np.resize(_,(3,3))
Out[200]: 
array([[8, 1, 8],
       [1, 8, 1],
       [8, 1, 8]])

That's not a very general solution, but then I don't know how you'd imagine generalizing the problem

Another way to expand and reshape

In [217]: np.repeat(t[[[0]],[2,1]],5,0).ravel()[:9].reshape(3,3)
Out[217]: 
array([[8, 1, 8],
       [1, 8, 1],
       [8, 1, 8]])
hpaulj
  • 221,503
  • 14
  • 230
  • 353