NumPy 다차원 배열의 i 번째 열에 액세스하는 방법은 무엇입니까?


463

내가 가지고 있다고 가정 해보십시오.

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

test[i]배열의 i 번째 줄을 얻습니다 (예 :)[1, 2] . i 번째 열에 어떻게 액세스 할 수 있습니까? (예 :) [1, 3, 5]. 또한 이것은 비싼 작업입니까?

답변:


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

비슷하게,

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

행에 액세스 할 수 있습니다. 이것은 NumPy 참조 의 1.4 (인덱싱) 섹션에서 다룹니다 . 적어도 내 경험상 이것은 빠르다. 루프에서 각 요소에 액세스하는 것보다 훨씬 빠릅니다.


11
이것은 사본을 생성하고 열에 대한 참조를 얻는 것처럼 참조를 얻을 수 있습니까?이 참조의 모든 변경 사항은 원래 배열에 반영됩니다.
harmands

@harmands 복사본을 만들지 않고 뷰를 만듭니다.
린스

69

한 번에 둘 이상의 열에 액세스하려면 다음을 수행하십시오.

>>> 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]])

물론이 경우 데이터 에만 액세스 하는 것이 아닙니다 . 당신은 사본을 반환합니다 (팬시 색인)
John Greenall

14
test[:,[0,2]]예를 들어 test[:, [0,2]] = something테스트를 수정하고 다른 배열을 만들지 않는 데이터에 액세스하기 만하면 됩니다. 그러나 copy_test = test[:, [0,2]]실제로 당신이 말하는대로 사본을 만듭니다.
Akavall

3
이것은 사본을 생성하고, 일부 열에 대한 참조를 얻는 것처럼 참조를 얻을 수 있습니까?이 참조의 변경 사항은 원래 배열에 반영됩니까?
harmands

@ harman786 수정 된 배열을 이전 배열로 다시 할당 할 수 있습니다.
Tamoghna Chowdhury

그렇지 않은 test[:,[0,2]]동안 왜 데이터에 액세스 test[:, [0, 2]][:, [0, 1]]합니까? 같은 일을 다시하는 것은 다른 결과를 가져 오는 것은 매우 직관적이지 않은 것 같습니다.
mapf

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

이 명령은 행 벡터를 제공합니다. 루프 벡터를 반복하고 싶다면 괜찮습니다. 그러나 차원이 3xN 인 다른 배열로 hstack하고 싶다면

ValueError: all the input arrays must have same number of dimensions

동안

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

연결 또는 hstack 작업을 수행 할 수 있도록 열 벡터를 제공합니다.

예 :

>>> np.hstack((test, test[:,[0]]))
array([[1, 2, 1],
       [3, 4, 3],
       [5, 6, 5]])

1
인덱싱은 한 번에 하나 이상의 열에 대해서도 작동하므로 마지막 예는 test [:, [0,1,0]] 또는 test [:, [range (test.shape [1]) + [0]] 일 수 있습니다. ]
lib

5
행 벡터가 아닌 열 벡터를 얻기 위해 [:, [0]] 대 [:, 0]을 지정하면 +1입니다. 정확히 내가 찾던 행동. 추가 인덱싱 노트를 위해 lib도 +1합니다. 이 답변은 최고의 답변과 함께 바로 위에 있어야합니다.
dhj

1
이 답변은 choosed 할 수 있어야합니다
구 세프 슬라바을

22

행을 바꾸고 반환 할 수도 있습니다.

In [4]: test.T[0]
Out[4]: array([1, 3, 5])

열에 액세스하는 가장 빠른 방법을 찾기 전에 한동안이 작업을 수행했습니다. 이것이 더 빠르거나 느리거나 test [:, [0]]와 같은지 궁금합니다.
José Chamorro


5

질문에 대한 답변이 있지만 뉘앙스에 대해 언급하겠습니다.

배열의 첫 번째 열에 관심이 있다고 가정 해 봅시다.

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

다른 답변에서 이미 알고 있듯이 "행 벡터"(array of shape (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µs가 걸렸습니다 A_c1_copy). 그러나 처음에 사본이 필요하거나 배열의 특정 열에 대해 여러 가지 다른 작업을 수행해야하고 속도를 위해 메모리를 희생하면 사본을 만드는 것이 좋습니다.

주로 열을 다루는 데 관심이있는 경우 행 주요 ( 'C') 순서 대신 열-주요 ( 'F') 순서로 배열을 만드는 것이 좋습니다. )을 누른 다음 열을 복사하지 않고 이전과 같이 슬라이싱을 수행하십시오.

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
>>> 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]])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.