Хотя на вопрос дан ответ, позвольте мне упомянуть некоторые нюансы.
Допустим, вас интересует первый столбец массива
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