numpy를 사용한 이상한 인덱싱


27

변수 x는 모양이 (2,2,50,100)입니다.

또한 np.array ([0,10,20])와 같은 배열 y가 있습니다. x [0, :, :, y]를 색인 할 때 이상한 일이 발생합니다.

x = np.full((2,2,50,100),np.nan)
y = np.array([0,10,20])
print(x.shape)
(2,2,50,100)
print(x[:,:,:,y].shape)
(2,2,50,3)
print(x[0,:,:,:].shape)
(2,50,100)
print(x[0,:,:,y].shape)
(3,2,50)

마지막 출력이 왜 (2,50,3)이 아닌 (3,2,50)을 출력합니까?


나는 numpy를 처음 사용하므로 귀하의 질문에 대한 답변이 없습니다. 더 자세히 조사하기 위해 2D 또는 3D에 불과하고 모든 축에서 최대 10 개의 요소와 같은 더 작은 예제를 찾는 것이 좋습니다.
코드 견습생

답변:


21

numpy가 고급 인덱싱을 사용하여 배열 모양을 브로드 캐스트하는 방법입니다. 0첫 번째 인덱스와 y마지막 인덱스에 대해 a 를 전달하면 numpy는와 0같은 모양으로 브로드 캐스트합니다 y. 다음과 같은 내용이 유지 x[0,:,:,y] == x[(0, 0, 0),:,:,y]됩니다. 여기에 예가 있습니다

import numpy as np

x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])

np.equal(x[0,:,:,y], x[(0, 0, 0),:,:,y]).all()
# returns:
True

이제 두 세트의 인덱스를 효과적으로 전달하기 때문에 고급 인덱싱 API를 사용하여 (이 경우) 인덱스 쌍을 형성합니다.

x[(0, 0, 0),:,:,y])

# equivalent to
[
  x[0,:,:,y[0]], 
  x[0,:,:,y[1]], 
  x[0,:,:,y[2]]
]

# equivalent to
rows = np.array([0, 0, 0])
cols = y
x[rows,:,:,cols]

# equivalent to
[
  x[r,:,:,c] for r, c in zip(rows, columns)
]

의 길이와 동일한 첫 번째 차원이 y있습니다. 이것이 당신이보고있는 것입니다.

예를 들어, 다음 청크에 설명 된 4 차원 배열을 살펴보십시오.

x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])

# x looks like:
array([[[[  0,   1,   2,   3,   4],    -+      =+
         [  5,   6,   7,   8,   9],     Sheet1  |
         [ 10,  11,  12,  13,  14],     |       |
         [ 15,  16,  17,  18,  19]],   -+       |
                                                Workbook1
        [[ 20,  21,  22,  23,  24],    -+       |
         [ 25,  26,  27,  28,  29],     Sheet2  |
         [ 30,  31,  32,  33,  34],     |       |
         [ 35,  36,  37,  38,  39]],   -+       |
                                                |
        [[ 40,  41,  42,  43,  44],    -+       |
         [ 45,  46,  47,  48,  49],     Sheet3  |
         [ 50,  51,  52,  53,  54],     |       |
         [ 55,  56,  57,  58,  59]]],  -+      =+


       [[[ 60,  61,  62,  63,  64],
         [ 65,  66,  67,  68,  69],
         [ 70,  71,  72,  73,  74],
         [ 75,  76,  77,  78,  79]],

        [[ 80,  81,  82,  83,  84],
         [ 85,  86,  87,  88,  89],
         [ 90,  91,  92,  93,  94],
         [ 95,  96,  97,  98,  99]],

        [[100, 101, 102, 103, 104],
         [105, 106, 107, 108, 109],
         [110, 111, 112, 113, 114],
         [115, 116, 117, 118, 119]]]])

x 우리가 지금 무슨 일이 일어나고 있는지 보여주기 위해 사용할 수있는 순차 양식을 이해하기가 정말 쉽습니다 ...

첫 번째 차원은 두 개의 Excel 통합 문서를 갖는 것과 같고 두 번째 차원은 각 통합 문서에 3 개의 시트를 갖는 것과 같으며, 세 번째 차원은 시트 당 4 개의 행을 갖는 것과 같으며 마지막 차원은 각 행 (또는 시트 당 열)에 대해 5 개의 값입니다.

이런 식으로 그것을 살펴보면 x[0,:,:,0]"첫 번째 통합 문서, 각 시트, 각 행에 대해 첫 번째 값 / 열을 알려주십시오."라고 말합니다.

x[0,:,:,y[0]]
# returns:
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])

# this is in the same as the first element in:
x[(0,0,0),:,:,y]

그러나 이제 고급 인덱싱을 사용 x[(0,0,0),:,:,y]하면 "첫 번째 통합 문서에서 각 시트의 각 행에 대해 나에게 y값 / 열을 제공합니다. 이제 각 값에 대해 수행합니다. y"

x[(0,0,0),:,:,y]
# returns:
array([[[ 0,  5, 10, 15],
        [20, 25, 30, 35],
        [40, 45, 50, 55]],

       [[ 2,  7, 12, 17],
        [22, 27, 32, 37],
        [42, 47, 52, 57]],

       [[ 4,  9, 14, 19],
        [24, 29, 34, 39],
        [44, 49, 54, 59]]])

그것이 열등한 곳은 numpy가 인덱스 배열 의 외부 치수 와 일치하도록 브로드 캐스트한다는 것 입니다. 따라서 위와 동일한 작업을 수행하지만 "Excel 통합 문서"모두에 대해 반복하고 연결하지 않아도됩니다. 당신은 첫 번째 차원에 배열을 전달 할 수 있지만, 반드시 호환되는 형태를 가지고있다.

정수를 전달하면에 브로드 캐스트됩니다 y.shape == (3,). 배열을 첫 번째 인덱스로 전달하려면 배열의 마지막 차원 만와 호환 가능해야 y.shape합니다. 즉, 첫 번째 인덱스의 마지막 차원은 3 또는 1이어야합니다.

ix = np.array([[0], [1]])
x[ix,:,:,y].shape
# each row of ix is broadcast to length 3:
(2, 3, 3, 4)

ix = np.array([[0,0,0], [1,1,1]])
x[ix,:,:,y].shape
# this is identical to above:
(2, 3, 3, 4)

ix = np.array([[0], [1], [0], [1], [0]])
x[ix,:,:,y].shape
# ix is broadcast so each row of ix has 3 columns, the length of y
(5, 3, 3, 4)

문서에서 간단한 설명을 찾았습니다. https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing


편집하다:

원래 질문에서 원하는 하위 슬라이스의 한 줄짜리를 얻으려면 다음을 사용할 수 있습니다 x[0][:,:,y].

x[0][:,:,y].shape
# returns
(2, 50, 3)

그러나 해당 하위 슬라이스 에 할당 하려는 경우 원래 배열의 공유 메모리 뷰를보고 있어야합니다. 그렇지 않으면 할당은 원래 배열이 아니라 사본이됩니다.

당신이 당신의 즉, 배열, 서브 세트 정수 또는 슬라이스를 사용할 때 공유 메모리에만 발생 x[:,0:3,:,:]또는 x[0,:,:,1:-1].

np.shares_memory(x, x[0])
# returns:
True

np.shares_memory(x, x[:,:,:,y])
# returns:
False

원래 질문과 예제 y에서 모두 정수 또는 슬라이스가 아니므로 항상 원본의 사본에 할당됩니다.

그러나! 귀하의 배열이 때문에 y슬라이스로 표현 될 수있다, 당신은 CAN 실제로 통해 배열의 할당보기를 얻을 :

x[0,:,:,0:21:10].shape
# returns:
(2, 50, 3)

np.shares_memory(x, x[0,:,:,0:21:10])
# returns:
True

# actually assigns to the original array
x[0,:,:,0:21:10] = 100

여기서는 슬라이스 0:21:10를 사용하여 에있는 모든 인덱스를 가져옵니다 range(0,21,10). 함수 에서와 같이 정지 점이 슬라이스에서 제외되므로 사용 21하지 않아야 합니다.20range

따라서 기본적으로 하위 슬라이스 기준에 맞는 슬라이스를 구성 할 수 있으면 할당을 수행 할 수 있습니다.


4

이라고 combining advanced and basic indexing합니다. 에서 combining advanced and basic indexing기본 색인의 차원 부분 공간 / CONCATENATE 결과를 먼저 고급 색인에 색인을하고 NumPy와.

문서의 예 :

x.shape를 (10,20,30,40,50)으로 하고 ind_1 및 ind_2를 모양 (2,3,4)으로 브로드 캐스트 할 수 있다고 가정하십시오. 그런 다음 X [:, ind_1, ind_2]의 모양은 (10,2,3,4,40,50)입니다. X의 (20,30) 모양 부분 공간이 (2,3,4) 부분 공간으로 대체 되었기 때문입니다. 지수. 그러나 x [:, ind_1, :, ind_2]의 모양은 (2,3,4,10,30,50) 이며, 색인 부분 공간에서 드롭 할 곳이 없기 때문에 시작 부분에 고정 됩니다. .transpose ()를 사용하여 원하는 곳으로 부분 공간을 이동할 수 있습니다. 이 예제는 take를 사용하여 복제 할 수 없습니다.

그래서,에 x[0,:,:,y], 0그리고 y사전 인덱싱 있습니다. 그들은 차원을 산출하기 위해 함께 방송됩니다 (3,).

In [239]: np.broadcast(0,y).shape
Out[239]: (3,)

이것은 (3,)2 차원과 3 차원의 시작 부분을 만들어(3, 2, 50)

1 차원과 마지막 차원이 실제로 함께 방송 되고 있는지 확인 0하기 [0,1]위해 로케일 오류를 보도록 변경하려고 할 수 있습니다.

print(x[[0,1],:,:,y])

Output:
IndexError                                Traceback (most recent call last)
<ipython-input-232-5d10156346f5> in <module>
----> 1 x[[0,1],:,:,y]

IndexError: shape mismatch: indexing arrays could not be broadcast together with
 shapes (2,) (3,)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.