Продвинутая нарезка.Высший порядок нарезки / выбора - PullRequest
0 голосов
/ 12 февраля 2019

Я запутался в семантике расширенного среза в некотором коде, который я нашел сегодня в нашей кодовой базе.Позвольте мне начать с примера:

# example boolean matrix
a = np.random.rand(5, 5) > 0.5

# Outputs
array([[ True, False,  True,  True, False],
       [ True,  True, False,  True, False],
       [False,  True,  True,  True,  True],
       [False, False, False, False,  True],
       [False,  True,  True, False, False]])
dim_1 = np.arange(5)
dim_1 = dim_1[:, None] # expand into ndarray :: (5,1)
dim_2 = np.eye(5,5).astype(int) # convert to ints so we can use as idx
a[dim_1, dim_2]

# Outputs
array([[False,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True],
       [False, False,  True, False, False],
       [False, False, False, False, False],
       [False, False, False, False,  True]])

Здесь мы наблюдаем, что dim_2 выбирает значения a.В этом примере мы видим [:, 1] вдоль глаза и a [:, 0] для оставшихся записей.Хотя я понимаю результат, я не понимаю семантику.Что меня действительно смутило, так это первое смутное изменение в (5,1).Результат совершенно другой без дополнительного измерения.Мое понимание продвинутой нарезки - то, что вы можете использовать более высокий порядок ndarray для индексации других ndarray, но только для выбора из последнего измерения.Чтобы достичь среза более высокого порядка, вам нужно индексировать каждое измерение отдельно, что возвращает вам плоский вектор.

Я думаю, что метод довольно аккуратный, но мне не хватает понимания того, как numpy выполняет синтаксический анализ этого среза.У кого-нибудь есть идеи?

1 Ответ

0 голосов
/ 12 февраля 2019

Создайте отличительный массив:

In [13]: a = np.arange(25).reshape(5,5)

In [14]: dim1 = np.arange(5)[:,None]
In [15]: dim2 = np.eye(5,5).astype(int)

Посмотрите, как эти два массива вещают друг с другом:

In [16]: np.broadcast_arrays(dim1, dim2)
Out[16]: 
[array([[0, 0, 0, 0, 0],
        [1, 1, 1, 1, 1],
        [2, 2, 2, 2, 2],
        [3, 3, 3, 3, 3],
        [4, 4, 4, 4, 4]]), 
 array([[1, 0, 0, 0, 0],
        [0, 1, 0, 0, 0],
        [0, 0, 1, 0, 0],
        [0, 0, 0, 1, 0],
        [0, 0, 0, 0, 1]])]

Возвращенный массив соответствует этим двум по форме, с элементами, выбранными изa путем сопряжения отдельных элементов от каждого.

In [17]: a[dim1, dim2]
Out[17]: 
array([[ 1,  0,  0,  0,  0],
       [ 5,  6,  5,  5,  5],
       [10, 10, 11, 10, 10],
       [15, 15, 15, 16, 15],
       [20, 20, 20, 20, 21]])

Для каждой строки, индексированной dim1, он выбирает элемент из столбца 0 или 1 в зависимости от значения dim2:

In [21]: a[0, dim2[0,:]]
Out[21]: array([1, 0, 0, 0, 0])
In [22]: a[3, dim2[3,:]]
Out[22]: array([15, 15, 15, 16, 15])

Если я изменю dim2 на «диагональ»

In [25]: dim2 = np.diag(np.arange(5))
In [26]: dim2
Out[26]: 
array([[0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0],
       [0, 0, 2, 0, 0],
       [0, 0, 0, 3, 0],
       [0, 0, 0, 0, 4]])
In [27]: a[dim1, dim2]
Out[27]: 
array([[ 0,  0,  0,  0,  0],
       [ 5,  6,  5,  5,  5],
       [10, 10, 12, 10, 10],
       [15, 15, 15, 18, 15],
       [20, 20, 20, 20, 24]])

Теперь большинство значений a[:,0], но диагонали a[i,i].

Это индексирование ничем не отличается от индексирования с помощью 1d-массивов, как в

In [28]: a[np.arange(5), np.arange(5)]
Out[28]: array([ 0,  6, 12, 18, 24])

a[0,0], a[1,1], a[2,2], ...

Еще один пример, который можно объяснить, передавая два массива друг против друга.При этом выбираются все элементы, такие же как a[:,:], за исключением того, что это копия, а не представление:

In [29]: a[np.arange(5)[:,None], np.arange(5)[None,:]]
Out[29]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...