Я изо всех сил пытаюсь выбрать определенные столбцы для каждой строки NumPy
матрицы.
Предположим, у меня есть следующая матрица, которую я бы назвал X
:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
У меня также есть list
индексы столбцов для каждой строки, которую я бы назвал Y
:
[1, 0, 2]
Мне нужно получить значения:
[2]
[4]
[9]
Вместо a list
с индексами Y
я также могу создать матрицу той же формы, X
где каждый столбец имеет значение bool
/ int
в диапазоне 0-1, указывая, является ли это обязательным столбцом.
[0, 1, 0]
[1, 0, 0]
[0, 0, 1]
Я знаю, что это можно сделать, перебирая массив и выбирая нужные мне значения столбцов. Однако это будет часто выполняться на больших массивах данных, и поэтому оно должно выполняться как можно быстрее.
Поэтому мне было интересно, есть ли лучшее решение?
Спасибо.
Ответы:
Если у вас есть логический массив, вы можете сделать прямой выбор на его основе следующим образом:
>>> a = np.array([True, True, True, False, False]) >>> b = np.array([1,2,3,4,5]) >>> b[a] array([1, 2, 3])
Чтобы продолжить свой первоначальный пример, вы можете сделать следующее:
>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> b = np.array([[False,True,False],[True,False,False],[False,False,True]]) >>> a[b] array([2, 4, 9])
Вы также можете добавить
arange
и сделать прямой выбор, хотя в зависимости от того, как вы генерируете свой логический массив и как выглядит ваш код YMMV.>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> a[np.arange(len(a)), [1,0,2]] array([2, 4, 9])
Надеюсь, это поможет, дайте мне знать, если у вас возникнут еще вопросы.
источник
arange
. Это было особенно полезно для меня при извлечении разных блоков из нескольких матриц (так что в основном трехмерный случай этого примера)arange
вместо:
? Я знаю, что ваш способ работает, а мой нет, но я хотел бы понять, почему.:
синтаксис работает иначе.:
с расширенной индексацией означает: «для каждого подпространства:
применять данную расширенную индексацию». Я правильно понимаю?Вы можете сделать что-то вроде этого:
In [7]: a = np.array([[1, 2, 3], ...: [4, 5, 6], ...: [7, 8, 9]]) In [8]: lst = [1, 0, 2] In [9]: a[np.arange(len(a)), lst] Out[9]: array([2, 4, 9])
Подробнее об индексировании многомерных массивов: http://docs.scipy.org/doc/numpy/user/basics.indexing.html#indexing-multi-dimensional-arrays
источник
:
будет выводить результаты несколькоlen(a)
раз, вместо этого, указав индекс каждой строки, напечатает ожидаемые результаты.Простой способ может выглядеть так:
In [1]: a = np.array([[1, 2, 3], ...: [4, 5, 6], ...: [7, 8, 9]]) In [2]: y = [1, 0, 2] #list of indices we want to select from matrix 'a'
range(a.shape[0])
вернетсяarray([0, 1, 2])
In [3]: a[range(a.shape[0]), y] #we're selecting y indices from every row Out[3]: array([2, 4, 9])
источник
В последних
numpy
версиях добавленtake_along_axis
(иput_along_axis
), который делает эту индексацию чисто.In [101]: a = np.arange(1,10).reshape(3,3) In [102]: b = np.array([1,0,2]) In [103]: np.take_along_axis(a, b[:,None], axis=1) Out[103]: array([[2], [4], [9]])
Действует так же, как:
In [104]: a[np.arange(3), b] Out[104]: array([2, 4, 9])
но с другой обработкой оси. Это особенно нацелено на применение результатов
argsort
иargmax
.источник
Вы можете сделать это с помощью итератора. Как это:
np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int)
Время:
N = 1000 X = np.zeros(shape=(N, N)) Y = np.arange(N) #@Aशwini चhaudhary %timeit X[np.arange(len(X)), Y] 10000 loops, best of 3: 30.7 us per loop #mine %timeit np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int) 1000 loops, best of 3: 1.15 ms per loop #mine %timeit np.diag(X.T[Y]) 10 loops, best of 3: 20.8 ms per loop
источник
np.diag(X.T[Y])
так медленно ... Ноnp.diag(X.T)
так быстро (10us). Не знаю почему.Другой умный способ - сначала транспонировать массив, а затем проиндексировать его. Наконец, возьмите диагональ, это всегда правильный ответ.
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) Y = np.array([1, 0, 2, 2]) np.diag(X.T[Y])
Шаг за шагом:
Исходные массивы:
>>> X array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9], [10, 11, 12]]) >>> Y array([1, 0, 2, 2])
Транспонируйте, чтобы его можно было правильно проиндексировать.
>>> X.T array([[ 1, 4, 7, 10], [ 2, 5, 8, 11], [ 3, 6, 9, 12]])
Получите строки в порядке Y.
>>> X.T[Y] array([[ 2, 5, 8, 11], [ 1, 4, 7, 10], [ 3, 6, 9, 12], [ 3, 6, 9, 12]])
Теперь диагональ должна стать четкой.
>>> np.diag(X.T[Y]) array([ 2, 4, 9, 12]
источник