Индексирование NumPy 2D-массива другим 2D-массивом - PullRequest
5 голосов
/ 27 марта 2012

У меня есть что-то вроде

m = array([[1, 2],
            [4, 5],
            [7, 8],
            [6, 2]])

и

select = array([0,1,0,0])

Моя цель

result = array([1, 5, 7, 6])

Я пытался _ix , когда я читалв Простое извлечение строки и столбца, numpy , но это не привело к тому, что я хотел.

ps Пожалуйста, измените название этого вопроса, если вы можете придумать более точный.

Ответы [ 6 ]

12 голосов
/ 24 августа 2012

numpy способ сделать это с помощью np.choose или необычной индексации / получения (см. Ниже):

m = array([[1, 2],
           [4, 5],
           [7, 8],
           [6, 2]])
select = array([0,1,0,0])

result = np.choose(select, m.T)

Так что нет необходимости в циклах Python, иличто угодно, со всеми преимуществами скорости, которые дает вам numpy.m.T просто необходим, потому что выбор действительно является более широким выбором между двумя массивами np.choose(select, (m[:,0], m[:1])), но использовать его вот так просто.


Использование необычного индексирования :

result = m[np.arange(len(select)), select]

И если скорость очень важна np.take, которая работает на одномерном изображении (по некоторым причинам это немного быстрее, но, возможно, не для этих крошечных массивов):

result = m.take(select+np.arange(0, len(select) * m.shape[1], m.shape[1]))
2 голосов
/ 27 марта 2012

Я предпочитаю использовать NP.where для индексации таких задач (а не NP.ix_ )

Что не упоминается в OP, так это то, выбран ли результат по местоположению (строка / столбец в исходном массиве) или по какому-либо условию (например, m> = 5). В любом случае приведенный ниже фрагмент кода охватывает оба сценария.

Три шага:

  1. создать массив условий ;

  2. генерирует индексный массив , вызывая NP.where , передавая это массив условий; и

  3. применить этот индексный массив к исходному массиву


>>> import numpy as NP

>>> cnd = (m==1) | (m==5) | (m==7) | (m==6)
>>> cnd
  matrix([[ True, False],
          [False,  True],
          [ True, False],
          [ True, False]], dtype=bool)

>>> # generate the index array/matrix 
>>> # by calling NP.where, passing in the condition (cnd)
>>> ndx = NP.where(cnd)
>>> ndx
  (matrix([[0, 1, 2, 3]]), matrix([[0, 1, 0, 0]]))

>>> # now apply it against the source array   
>>> m[ndx]
  matrix([[1, 5, 7, 6]])


Аргумент, передаваемый NP.where, cnd , является логическим массивом, который в данном случае является результатом одного выражения, состоящего из составных условных выражений (первая строка выше)

Если создание такого фильтра значений не относится к вашему конкретному случаю использования, это нормально, вам просто нужно сгенерировать фактическую логическую матрицу (значение cnd ) другим способом (или создайте его напрямую).

1 голос
/ 03 августа 2017

Поскольку заголовок относится к индексации массива 2D с помощью другого массива 2D , общее решение по крошке можно найти здесь .

Короче говоря: 2D-массив индексов формы (n, m) с произвольным большим размером m с именем inds используется для доступа к элементам другого 2D-массива формы (n, k), по имени B :

# array of index offsets to be added to each row of inds
offset = np.arange(0, inds.size, inds.shape[1])

# numpy.take(B, C) "flattens" arrays B and C and selects elements from B based on indices in C
Result = np.take(B, offset[:,np.newaxis]+inds)
1 голос
/ 27 марта 2012

А как насчет использования Python?

result = array([subarray[index] for subarray, index in zip(m, select)])
0 голосов
/ 15 мая 2015

ИМХО, это самый простой вариант:

m[np.arange(4), select]
0 голосов
/ 27 марта 2012
result = array([m[j][0] if i==0 else m[j][1] for i,j in zip(select, range(0, len(m)))])
...