programing

NumPy 2d 배열의 슬라이싱 또는 nxn 배열(n>m)에서 mxm 하위 매트릭스를 추출하는 방법은 무엇입니까?

lastmoon 2023. 7. 1. 09:17
반응형

NumPy 2d 배열의 슬라이싱 또는 nxn 배열(n>m)에서 mxm 하위 매트릭스를 추출하는 방법은 무엇입니까?

NumPinxn 배열을 슬라이스하고 싶습니다.해당 배열의 행과 열을 임의로 선택하여 추출(예: 행/열 수에 패턴이 없음)하여 새 mxm 배열로 만듭니다.이 예에서는 어레이가 4x4이고 여기서 2x2 어레이를 추출하려고 합니다.

다음은 당사의 어레이입니다.

from numpy import *
x = range(16)
x = reshape(x,(4,4))

print x
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

제거할 선과 열이 동일합니다.가장 쉬운 경우는 시작 부분이나 끝 부분에 있는 2x2 하위 매트릭스를 추출하려는 경우입니다. 예:

In [33]: x[0:2,0:2]
Out[33]: 
array([[0, 1],
       [4, 5]])

In [34]: x[2:,2:]
Out[34]: 
array([[10, 11],
       [14, 15]])

그러나 행/열이 혼합된 다른 항목을 제거해야 하는 경우에는 어떻게 해야 합니까?첫 번째와 세 번째 행/행을 제거하여 하위 매트릭스를 추출해야 하는 경우[[5,7],[13,15]]임의의 행/라인 구성이 있을 수 있습니다.행과 열 모두에 대해 배열/색인 목록을 사용하여 어레이를 인덱싱하기만 하면 된다는 내용을 어디선가 읽었지만, 작동하지 않는 것 같습니다.

In [35]: x[[1,3],[1,3]]
Out[35]: array([ 5, 15])

한 가지 방법을 찾았어요. 바로 다음과 같습니다.

    In [61]: x[[1,3]][:,[1,3]]
Out[61]: 
array([[ 5,  7],
       [13, 15]])

이것에 대한 첫 번째 문제는 제가 그것을 견딜 수는 있지만 읽기 어렵다는 것입니다.누군가 더 좋은 해결책이 있다면 꼭 듣고 싶습니다.

또한 포럼에서 읽은 바에 따르면 어레이가 포함된 인덱싱 어레이는 NumPy가 원하는 어레이의 복사본을 만들 수 있으므로 대규모 어레이로 처리할 때 문제가 될 수 있습니다.왜 그럴까요? / 이 메커니즘은 어떻게 작동하나요?

이 질문에 답하려면 Numpy에서 다차원 배열 인덱싱이 어떻게 작동하는지 살펴봐야 합니다.먼저 당신이 그 배열을 가지고 있다고 가정해 보겠습니다.x당신의 질문에서.에 입니다.x0까지의 의 오름차순 합니다.한 요소에 액세스할 경우 다음과 같이 말합니다.x[i,j]NumPy는 버퍼의 시작을 기준으로 이 요소의 메모리 위치를 파악해야 합니다.으로 계산함으로써 이루어집니다.i*x.shape[1]+j실제 메모리 오프셋을 얻기 위해 int 크기를 곱합니다.

다음과 같이 기본적인 슬라이싱으로 서브어레이를 추출하면y = x[0:2,0:2]된 객체는 기본 를 결과개버공유다니합과 합니다.x 당신이 하만당접어될떻까요게면속하지신이에 ?y[i,j]는 NumPy를 수 .i*y.shape[1]+j가 오에속데때문프계산에 y메모리가 연속적이지 않습니다.

NumPy는 약진을 도입하여 이 문제를 해결합니다.액세스를 위한 메모리 오프셋을 계산할 때x[i,j]은 실로계된것은입니다.i*x.strides[0]+j*x.strides[1] int의 하고 있습니다int는 int의 크기에 대한 인자입니다.)

x.strides
(16, 4)

y위와 같이 추출되며, NumPy는 새 버퍼를 만들지 않지만 동일한 버퍼를 참조하는 새 어레이 개체를 만듭니다(그렇지 않으면).y와 동등할 것입니다.x 새 것입니다.) 그러면새개모달양다니라집이의체배열▁.다니▁will달집라▁object▁then.x그리고 버퍼에 다른 시작 오프셋이 있을 수 있지만, 진전을 공유할 것입니다.x 이 으)로 표시됩니다.

y.shape
(2,2)
y.strides
(16, 4)

오프셋을 합니다.y[i,j]정확한 결과를 얻을 수 있습니다.

하지만 는 NumPy와 같은 요?z=x[[1,3]]원래 버퍼가 다음에 사용되는 경우에는 단계 메커니즘에서 올바른 인덱싱을 허용하지 않습니다.zNumPy는 이론적으로 보폭보다 더 정교한 메커니즘을 추가할 수 있지만, 이는 요소 액세스를 상대적으로 비싸게 만들어 배열의 전체 아이디어를 무시합니다.게다가, 뷰는 더 이상 정말 가벼운 물체가 아닙니다.

이에 대한 자세한 내용은 인덱싱에 대한 NumPy 설명서에 나와 있습니다.

아, 그리고 당신의 실제 질문에 대해 거의 잊어버렸습니다.다음은 여러 목록이 포함된 인덱싱이 예상대로 작동하도록 하는 방법입니다.

x[[[1],[3]],[1,3]]

인덱스 배열이 공통 모양으로 브로드캐스트되기 때문입니다.물론 이 예에서는 기본적인 슬라이싱도 사용할 수 있습니다.

x[1::2, 1::2]

언급했듯이, 스이언급이듯했벤,이▁as,x[[[0],[2]],[1,3]]1및 3 하는 0 및 2하며, 1 및 3 는 0 및 2 합 2 니 다 반x[[0,2],[1,3]]배열에서 x[0,1] 및 x[2,3] 값을 반환합니다.

제가 처음으로 제시한 예시를 수행하는 데 도움이 되는 기능이 있습니다.numpy.ix_첫 번째 예와 동일한 작업을 수행할 수 있습니다.x[numpy.ix_([0,2],[1,3])]이렇게 하면 추가 대괄호를 모두 입력하지 않아도 됩니다.

나는 그렇게 생각하지 않는다.x[[1,3]][:,[1,3]]거의 읽을 수 없습니다.당신의 의도를 더 명확히 하고 싶다면, 당신은 다음을 할 수 있습니다.

a[[1,3],:][:,[1,3]]

저는 슬라이싱 전문가는 아니지만 일반적으로 배열로 슬라이스하려고 시도하고 값이 연속적인 경우 스트라이드 값이 변경되는 뷰를 다시 얻을 수 있습니다.

예를 들어 입력 33과 34에서는 2x2 배열을 사용하지만 스트라이드는 4입니다.따라서 다음 행을 인덱싱할 때 포인터가 메모리의 올바른 위치로 이동합니다.

분명히, 이 메커니즘은 일련의 지수의 경우에 잘 적용되지 않습니다.따라서, numpy는 복사를 해야 할 것입니다.결국, 많은 다른 행렬 산술 함수는 크기, 스트라이드 및 연속 메모리 할당에 의존합니다.

다른 모든 행과 다른 열을 건너뛰려면 기본 슬라이싱을 사용하여 다음 작업을 수행할 수 있습니다.

In [49]: x=np.arange(16).reshape((4,4))
In [50]: x[1:4:2,1:4:2]
Out[50]: 
array([[ 5,  7],
       [13, 15]])

그러면 배열의 복사본이 아닌 보기가 반환됩니다.

In [51]: y=x[1:4:2,1:4:2]

In [52]: y[0,0]=100

In [53]: x   # <---- Notice x[1,1] has changed
Out[53]: 
array([[  0,   1,   2,   3],
       [  4, 100,   6,   7],
       [  8,   9,  10,  11],
       [ 12,  13,  14,  15]])

하는 동안에z=x[(1,3),:][:,(1,3)]고급 인덱싱을 사용하여 복사본을 반환합니다.

In [58]: x=np.arange(16).reshape((4,4))
In [59]: z=x[(1,3),:][:,(1,3)]

In [60]: z
Out[60]: 
array([[ 5,  7],
       [13, 15]])

In [61]: z[0,0]=0

:x변경되지 않음:

In [62]: x
Out[62]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

임의의 행과 열을 선택하려면 기본 슬라이싱을 사용할 수 없습니다.인덱싱을 . 예를 들어, " 급인덱을합다니야사"와 같은 x[rows,:][:,columns]서, 디에어rows그리고.columns시입니다 ▁this다니. 이것은 입니다.물론 이것은 보기가 아니라 원래 배열의 복사본을 제공할 것입니다.numpy 배열은 연속적인 메모리를 사용하기 때문에(일정한 단계로), 임의의 행과 열로 뷰를 생성할 수 없습니다(일정하지 않은 단계가 필요하므로).

numpy를 사용하면 인덱스의 각 구성 요소에 대한 슬라이스를 전달할 수 있습니다. 따라서,x[0:2,0:2]위 작품들의 예시.

열이나 행을 고르게 건너뛰려면 세 가지 성분(예: 시작, 중지, 단계)으로 슬라이스를 전달할 수 있습니다.

위의 예에 대해서도 마찬가지입니다.

>>> x[1:4:2, 1:4:2]
array([[ 5,  7],
       [13, 15]])

기본적으로 첫 번째 차원에서 슬라이스하고 인덱스 1에서 시작하며 인덱스가 4 이상일 때 중지하고 각 패스에서 인덱스에 2를 추가합니다.두 번째 차원도 마찬가지입니다.다시 말하지만, 이것은 일정한 단계에서만 작동합니다.

내부적으로 상당히 다른 것을 해야 하는 구문 - 무엇.x[[1,3]][:,[1,3]]실제로는 원래 배열에서 1행과 3행만 포함하는 새 배열을 만듭니다(이를 통해 수행됨).x[[1,3]]part를 선택한 -array.part의 하여 세 배열을 함)을 합니다.

저도 비슷한 질문이 있습니다. 가장 피톤체적인 방식으로 하위 배열과 배열로 글을 쓰는 것입니다. 파이썬 2.

귀하의 사례에 대한 이전 게시물의 솔루션에 따르면 솔루션은 다음과 같습니다.

columns_to_keep = [1,3] 
rows_to_keep = [1,3]

ix_:를 사용한 A:

x[np.ix_(rows_to_keep, columns_to_keep)] 

즉,

array([[ 5,  7],
       [13, 15]])

이것이 얼마나 효율적인지는 모르겠지만 범위()를 사용하여 양쪽 축에서 슬라이스할 수 있습니다.

 x=np.arange(16).reshape((4,4))
 x[range(1,3), :][:,range(1,3)] 

언급URL : https://stackoverflow.com/questions/4257394/slicing-of-a-numpy-2d-array-or-how-do-i-extract-an-mxm-submatrix-from-an-nxn-ar

반응형