Câu trả lời:
>>> test[:,0]
array([1, 3, 5])
Tương tự
>>> test[1,:]
array([3, 4])
cho phép bạn truy cập các hàng. Điều này được trình bày trong Mục 1.4 (Lập chỉ mục) của tham chiếu NumPy . Điều này là nhanh chóng, ít nhất là theo kinh nghiệm của tôi. Nó chắc chắn nhanh hơn nhiều so với việc truy cập từng phần tử trong một vòng lặp.
Và nếu bạn muốn truy cập nhiều cột cùng một lúc, bạn có thể làm:
>>> 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]])
test[:,[0,2]]
chỉ cần truy cập dữ liệu, ví dụ, test[:, [0,2]] = something
sẽ sửa đổi kiểm tra và không tạo ra một mảng khác. Nhưng copy_test = test[:, [0,2]]
trên thực tế tạo ra một bản sao như bạn nói.
test[:,[0,2]]
chỉ truy cập dữ liệu trong khi test[:, [0, 2]][:, [0, 1]]
không? Có vẻ rất không trực quan khi làm điều tương tự một lần nữa có kết quả khác nhau.
>>> test[:,0]
array([1, 3, 5])
lệnh này cung cấp cho bạn một vectơ hàng, nếu bạn chỉ muốn lặp qua nó, thì tốt thôi, nhưng nếu bạn muốn hstack với một số mảng khác có kích thước 3xN, bạn sẽ có
ValueError: all the input arrays must have same number of dimensions
trong khi
>>> test[:,[0]]
array([[1],
[3],
[5]])
cung cấp cho bạn một vectơ cột, để bạn có thể thực hiện thao tác ghép hoặc hstack.
ví dụ
>>> np.hstack((test, test[:,[0]]))
array([[1, 2, 1],
[3, 4, 3],
[5, 6, 5]])
Bạn cũng có thể hoán chuyển và trả về một hàng:
In [4]: test.T[0]
Out[4]: array([1, 3, 5])
Để có được một số cột và độc lập, chỉ cần:
> test[:,[0,2]]
bạn sẽ nhận được colums 0 và 2
Mặc dù câu hỏi đã được trả lời, hãy để tôi đề cập đến một số sắc thái.
Giả sử bạn quan tâm đến cột đầu tiên của mảng
arr = numpy.array([[1, 2],
[3, 4],
[5, 6]])
Như bạn đã biết từ các câu trả lời khác, để có được nó ở dạng "vectơ hàng" (mảng hình dạng (3,)
), bạn sử dụng cắt:
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
Để kiểm tra xem một mảng là một khung nhìn hay một bản sao của một mảng khác, bạn có thể làm như sau:
arr_c1_ref.base is arr # True
arr_c1_copy.base is arr # False
xem ndarray.base .
Bên cạnh sự khác biệt rõ ràng giữa hai (sửa đổi arr_c1_ref
sẽ ảnh hưởngarr
), số bước byte để duyệt qua từng bước là khác nhau:
arr_c1_ref.strides[0] # 8 bytes
arr_c1_copy.strides[0] # 4 bytes
xem sải chân . Sao nó lại quan trọng? Hãy tưởng tượng rằng bạn có một mảng rất lớn A
thay vìarr
:
A = np.random.randint(2, size=(10000,10000), dtype='int32')
A_c1_ref = A[:, 1]
A_c1_copy = A[:, 1].copy()
và bạn muốn tính tổng của tất cả các phần tử của cột đầu tiên, tức là A_c1_ref.sum()
hoặc A_c1_copy.sum()
. Sử dụng phiên bản sao chép nhanh hơn nhiều:
%timeit A_c1_ref.sum() # ~248 µs
%timeit A_c1_copy.sum() # ~12.8 µs
Điều này là do số bước tiến khác nhau được đề cập trước đó:
A_c1_ref.strides[0] # 40000 bytes
A_c1_copy.strides[0] # 4 bytes
Mặc dù có vẻ như việc sử dụng các bản sao cột là tốt hơn, nhưng không phải lúc nào cũng đúng vì lý do tạo một bản sao cần có thời gian và sử dụng nhiều bộ nhớ hơn (trong trường hợp này, tôi phải mất khoảng 200 Van để tạo ra A_c1_copy
). Tuy nhiên, nếu chúng ta cần bản sao ở vị trí đầu tiên hoặc chúng ta cần thực hiện nhiều thao tác khác nhau trên một cột cụ thể của mảng và chúng ta vẫn ổn với việc hy sinh bộ nhớ cho tốc độ, thì việc tạo một bản sao là cách tốt nhất.
Trong trường hợp chúng tôi quan tâm đến việc làm việc chủ yếu với các cột, có thể là một ý tưởng tốt để tạo mảng của chúng tôi theo thứ tự cột chính ('F') thay vì thứ tự hàng chính ('C') (là mặc định ), và sau đó thực hiện cắt lát như trước để có được một cột mà không cần sao chép nó:
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
Bây giờ, thực hiện thao tác tính tổng (hoặc bất kỳ thao tác nào khác) trên chế độ xem cột nhanh hơn nhiều.
Cuối cùng, tôi xin lưu ý rằng việc hoán chuyển một mảng và sử dụng tính năng cắt hàng cũng giống như sử dụng việc cắt cột trên mảng ban đầu, bởi vì việc hoán vị được thực hiện chỉ bằng cách hoán đổi hình dạng và các bước của mảng ban đầu.
A.T[1,:].strides[0] # 40000