Как получить доступ к i-му столбцу многомерного массива NumPy? - PullRequest
382 голосов
/ 16 декабря 2010

Предположим, у меня есть:

test = numpy.array([[1, 2], [3, 4], [5, 6]])

test[i] возвращает меня ith строка массива (например, [1, 2]). Как я могу получить доступ к столбцу ith ? (например, [1, 3, 5]). Кроме того, это будет дорогая операция?

Ответы [ 7 ]

570 голосов
/ 16 декабря 2010
>>> test[:,0]
array([1, 3, 5])

Аналогично,

>>> test[1,:]
array([3, 4])

позволяет получить доступ к строкам. Это описано в разделе 1.4 (Индексация) справки NumPy . Это быстро, по крайней мере, по моему опыту. Это, конечно, намного быстрее, чем доступ к каждому элементу в цикле.

59 голосов
/ 20 апреля 2013

И если вы хотите получить доступ к нескольким столбцам одновременно, вы можете сделать:

>>> test = np.arange(9).reshape((3,3))
>>> test
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> test[:,[0,2]]
array([[0, 2],
       [3, 5],
       [6, 8]])
46 голосов
/ 10 апреля 2014
>>> test[:,0]
array([1, 3, 5])

эта команда дает вам вектор строки, если вы просто хотите зациклить его, это нормально, но если вы хотите выполнить hstack с другим массивом с размером 3xN, у вас будет

ValueError: все входные массивы должны иметь одинаковое количество измерений

, а

>>> test[:,[0]]
array([[1],
       [3],
       [5]])

дает вам вектор столбца, так что вы можете выполнять конкатенацию или операцию hstack.

, например

>>> np.hstack((test, test[:,[0]]))
array([[1, 2, 1],
       [3, 4, 3],
       [5, 6, 5]])
20 голосов
/ 26 января 2016

Вы также можете транспонировать и возвращать строку:

In [4]: test.T[0]
Out[4]: array([1, 3, 5])
3 голосов
/ 25 октября 2018

Хотя на вопрос дан ответ, позвольте мне упомянуть некоторые нюансы.

Допустим, вас интересует первый столбец массива

arr = numpy.array([[1, 2],
                   [3, 4],
                   [5, 6]])

Как вы уже знаете из других ответов, чтобы получить его в виде "вектора строки" (массив формы (3,)), вы используете нарезку:

arr_c1_ref = arr[:, 1]  # creates a reference to the 1st column of the arr
arr_c1_copy = arr[:, 1].copy()  # creates a copy of the 1st column of the arr

Чтобы проверить, является ли массив представлением или копией другого массива, вы можете сделать следующее:

arr_c1_ref.base is arr  # True
arr_c1_copy.base is arr  # False

см. ndarray.base .

Помимо очевидного различия между ними (изменение arr_c1_ref повлияет на arr), количество байтовых шагов для обхода каждого из них различно:

arr_c1_ref.strides[0]  # 8 bytes
arr_c1_copy.strides[0]  # 4 bytes

см. шагов . Почему это важно? Представьте, что у вас есть очень большой массив A вместо arr:

A = np.random.randint(2, size=(10000,10000), dtype='int32')
A_c1_ref = A[:, 1] 
A_c1_copy = A[:, 1].copy()

и вы хотите вычислить сумму всех элементов первого столбца, то есть A_c1_ref.sum() или A_c1_copy.sum(). Использование скопированной версии намного быстрее:

%timeit A_c1_ref.sum()  # ~248 µs
%timeit A_c1_copy.sum()  # ~12.8 µs

Это связано с разным количеством шагов, упомянутых ранее:

A_c1_ref.strides[0]  # 40000 bytes
A_c1_copy.strides[0]  # 4 bytes

Хотя может показаться, что лучше использовать копии столбцов, это не всегда так, потому что создание копии занимает много времени и требует больше памяти (в этом случае мне понадобилось около 200 мкс для создания A_c1_copy) , Однако, если нам нужна копия в первую очередь или нам нужно выполнить много разных операций с определенным столбцом массива, и мы в порядке с потерей памяти ради скорости, то создание копии - это путь.

В случае, если мы заинтересованы в работе в основном со столбцами, было бы неплохо создать наш массив в мажорном столбце ('F'), а не в мажорном ряду ('C') (который по умолчанию), а затем выполните нарезку, как раньше, чтобы получить столбец без его копирования:

A = np.asfortranarray(A)  # or np.array(A, order='F')
A_c1_ref = A[:, 1]
A_c1_ref.strides[0]  # 4 bytes
%timeit A_c1_ref.sum()  # ~12.6 µs vs ~248 µs

Теперь выполнение операции суммирования (или любой другой) в представлении столбца выполняется намного быстрее.

В заключение позвольте мне отметить, что транспонирование массива и использование нарезки строк - это то же самое, что и нарезка столбцов в исходном массиве, потому что транспонирование выполняется просто путем замены формы и шагов исходного массива.

A.T[1,:].strides[0]  # 40000
3 голосов
/ 07 марта 2018

Чтобы получить несколько и независимых столбцов, просто:

> test[:,[0,2]]

вы получите столбцы 0 и 2

2 голосов
/ 21 ноября 2015
>>> test
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

>>> ncol = test.shape[1]
>>> ncol
5L

Затем вы можете выбрать 2-4 столбец следующим образом:

>>> test[0:, 1:(ncol - 1)]
array([[1, 2, 3],
       [6, 7, 8]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...