numpy.array 모양 (R, 1)과 (R,)의 차이점


319

에서은 numpy, 작업 중 일부는 형태로 반환 (R, 1)하지만 일부 반환 (R,). 이것은 명시 적 reshape으로 요구 되기 때문에 행렬 곱셈을 더 지루하게 만듭니다 . 예를 들어, 행렬이 주어진 M경우 행 수를 numpy.dot(M[:,0], numpy.ones((1, R)))어디 에서 수행 R하려면 열 방향으로 동일한 문제가 발생합니다. 우리는 얻을 것이다 matrices are not aligned이후 오류 M[:,0]모양입니다 (R,)numpy.ones((1, R))모양이다 (1, R).

그래서 내 질문은 :

  1. 모양의 차이 무엇 (R, 1)(R,). 문자 그대로 숫자 목록과 모든 목록에 숫자 만 포함 된 목록 목록이라는 것을 알고 있습니다. 더 쉬운 행렬 곱셈 대신 numpy모양 (R, 1)을 선호하도록 디자인하지 않는 이유가 궁금 (R,)합니다.

  2. 위의 예에 더 좋은 방법이 있습니까? 명시 적으로 다음과 같이 재구성하지 마십시오.numpy.dot(M[:,0].reshape(R, 1), numpy.ones((1, R)))


3
도움 될 수 있습니다. 실용적인 해결책을 찾는 것이 아닙니다.
keyser

1
적절한 해결책 : numpy.ravel (M [:, 0])-모양을 (R, 1)에서 (R,)로 변환
Andi R

답변:


544

1. NumPy에서 도형의 의미

"말 그대로 숫자 목록과 모든 목록에 숫자 만 포함되어있는 목록의 목록이라는 것을 알고 있습니다."라고 생각하면 약간 도움이되지 않습니다.

NumPy와 배열에 대해 생각하는 가장 좋은 방법은 두 부분으로 구성되어 있다는 점이다 데이터 버퍼 단지 원시 요소의 블록 및 인 데이터 버퍼를 해석하는 방법에 대해 설명합니다.

예를 들어, 12 개의 정수 배열을 만드는 경우 :

>>> a = numpy.arange(12)
>>> a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

그런 다음 a데이터 버퍼로 구성되며 다음과 같이 정렬됩니다.

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

데이터를 해석하는 방법을 설명하는보기 :

>>> a.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
>>> a.dtype
dtype('int64')
>>> a.itemsize
8
>>> a.strides
(8,)
>>> a.shape
(12,)

여기서 모양 (12,) 은 배열이 0에서 11까지 실행되는 단일 색인으로 색인화됨을 의미합니다. 개념적으로이 단일 색인에 레이블을 지정 i하면 배열 a은 다음과 같습니다.

i= 0    1    2    3    4    5    6    7    8    9   10   11
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

우리가하면 바꿀 배열을,이 데이터 버퍼를 변경하지 않습니다. 대신, 데이터를 해석하는 다른 방법을 설명하는 새보기를 작성합니다. 그래서 후 :

>>> b = a.reshape((3, 4))

배열은와 b동일한 데이터 버퍼를 a갖지만 이제는 각각 0에서 2, 0에서 3까지 실행 되는 두 개의 인덱스로 인덱스됩니다. 우리는 두 개의 인덱스 라벨 경우 ij, 배열 b과 같은 모양을 :

i= 0    0    0    0    1    1    1    1    2    2    2    2
j= 0    1    2    3    0    1    2    3    0    1    2    3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

의미하는 것은:

>>> b[2,1]
9

두 번째 인덱스가 빠르게 변경되고 첫 번째 인덱스가 느리게 변경되는 것을 볼 수 있습니다. 이것을 다른 방식으로 선호하는 경우 order매개 변수를 지정할 수 있습니다 .

>>> c = a.reshape((3, 4), order='F')

그러면 다음과 같이 색인이 생성 된 배열이 생성됩니다.

i= 0    1    2    0    1    2    0    1    2    0    1    2
j= 0    0    0    1    1    1    2    2    2    3    3    3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

의미하는 것은:

>>> c[2,1]
5

이제 배열의 크기가 1 이상인 모양을 갖는 것이 무엇을 의미하는지 분명해야합니다.

>>> d = a.reshape((12, 1))

배열 d은 두 개의 인덱스로 인덱스되며 첫 번째 인덱스는 0에서 11까지이며 두 번째 인덱스는 항상 0입니다.

i= 0    1    2    3    4    5    6    7    8    9   10   11
j= 0    0    0    0    0    0    0    0    0    0    0    0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

그래서 :

>>> d[10,0]
10

길이 1의 차원은 "무료"(어떤 의미에서), 그래서 당신이 도시에가는 것을 막을 수있는 것은 없습니다 :

>>> e = a.reshape((1, 2, 1, 6, 1))

다음과 같이 색인이 생성 된 배열을 제공합니다.

i= 0    0    0    0    0    0    0    0    0    0    0    0
j= 0    0    0    0    0    0    1    1    1    1    1    1
k= 0    0    0    0    0    0    0    0    0    0    0    0
l= 0    1    2    3    4    5    0    1    2    3    4    5
m= 0    0    0    0    0    0    0    0    0    0    0    0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

그래서 :

>>> e[0,1,0,0,0]
6

참고 항목 NumPy와 내부 문서 배열 구현하는 방법에 대한 자세한 내용을.

2. 무엇을해야합니까?

때문에 numpy.reshape단지 새로운 뷰를 작성, 당신은 필요할 때마다 그것을 사용하는 방법에 대해 두려워해서는 안된다. 배열을 다른 방식으로 인덱싱하려는 경우 사용하는 올바른 도구입니다.

그러나 계산 시간이 길면 일반적으로 처음에 "올바른"모양으로 배열을 구성 할 수 있으므로 모양 변경 및 조옮김 횟수를 최소화 할 수 있습니다. 그러나 실제 상황을 보지 않으면 서 재구성해야 할 필요성이 무엇인지, 변경해야 할 것을 말하기는 어렵습니다.

귀하의 질문에 예는 다음과 같습니다

numpy.dot(M[:,0], numpy.ones((1, R)))

그러나 이것은 현실적이지 않습니다. 먼저,이 표현은 :

M[:,0].sum()

더 간단하게 결과를 계산합니다. 둘째, 실제로 열 0에 특별한 것이 있습니까? 아마도 실제로 필요한 것은 다음과 같습니다.

M.sum(axis=0)

33
이것은 배열이 어떻게 저장되는지 생각하는 데 매우 도움이되었습니다. 감사합니다! 추가 행렬 계산을 위해 (2-d) 행렬의 열 (또는 행)에 액세스하는 것은 항상 열을 적절하게 재구성해야하기 때문에 불편합니다. 매번 모양을 (n,)에서 (n, 1)으로 변경해야합니다.
OfLettersAndNumbers

3
@SammyLee : 사용 newaxis예제는 당신이, 또 다른 축이 필요한 경우 a[:, j, np.newaxis]는 IS j의 번째 열 a, 그리고 a[np.newaxis, i]는 IS i번째 행.
Gareth Rees

나는이 모델에 의해 종이에 대한 더 나은 이해를 얻기 위해 인덱스를 플롯하려고 노력하고 있는데 모양이 2 x 2 x 4 인 경우 첫 번째 2는 0000000011111111로 이해할 수 있으며 마지막 4는 0123012301230123으로 이해 중간에 어떤 일이 발생합니까?
PirateApp

3
이것을 쉽게 생각할 수있는 방법은 numpy가 예상대로 정확하게 작동하지만 Python의 튜플 인쇄가 잘못 될 수 있다는 것입니다. 이 (R, )경우 모양은 ndarray단일 요소가 포함 된 튜플이므로 뒤에 쉼표가있는 Python으로 인쇄됩니다. 추가 쉼표가 없으면 괄호 안에 표현모호합니다 . ndarray단일 차원을 가진 A 는 length의 열 벡터로 간주 될 수 있습니다 R. 이 (R, 1)경우 튜플에는 두 가지 요소가 있으므로 행 벡터 (또는 1 행 길이의 행렬)로 생각할 수 있습니다 R.
Michael Yang

1
@ Alex-droidAD : 이 질문 과 답변을 참조하십시오 .
Gareth Rees

16

의 차이 (R,)와는 (1,R)그대로 사용할 필요가 인덱스의 수입니다. ones((1,R))행이 하나만있는 2 차원 배열입니다. ones(R)벡터입니다. 일반적으로 변수에 둘 이상의 행 / 열이있는 것이 이치에 맞지 않으면 단일 크기의 행렬이 아닌 벡터를 사용해야합니다.

특정한 경우에는 몇 가지 옵션이 있습니다.

1) 두 번째 인수를 벡터로 만드십시오. 다음은 잘 작동합니다.

    np.dot(M[:,0], np.ones(R))

2) 매트릭스 작업과 같은 MATLAB을 원하면 matrix대신 클래스 를 사용하십시오 ndarray. 모든 수학은 2 차원 배열이되어야하며 연산자 *는 요소 단위 대신 행렬 곱셈을 수행하므로 점이 필요하지 않습니다. 내 경험상, 이것은 가치가있는 더 많은 문제이지만 matlab에 익숙하다면 좋을 수도 있습니다.


예. 나는 더 matlab과 같은 행동을 기대하고있었습니다. matrix수업을 살펴 보겠습니다 . matrix클래스 BTW 의 문제점은 무엇입니까 ?
clwen

2
문제 matrix는 2D에 불과하고 연산자 '*'에 과부하가 걸리기 때문에에 ndarray사용하면 작성된 함수 가 실패 할 수 있다는 것 matrix입니다.
Evan

11

모양은 튜플입니다. 1 차원 만있는 경우 모양은 하나의 숫자이며 쉼표 뒤에 공백이됩니다. 2+ 차원의 경우 모든 쉼표 뒤에 숫자가 있습니다.

# 1 dimension with 2 elements, shape = (2,). 
# Note there's nothing after the comma.
z=np.array([  # start dimension
    10,       # not a dimension
    20        # not a dimension
])            # end dimension
print(z.shape)

(2,)

# 2 dimensions, each with 1 element, shape = (2,1)
w=np.array([  # start outer dimension 
    [10],     # element is in an inner dimension
    [20]      # element is in an inner dimension
])            # end outer dimension
print(w.shape)

(2,1)


5

기본 배열 클래스의 경우 2d 배열은 1d 또는 3d 배열보다 더 특별하지 않습니다. 치수를 유지하는 일부 작업이 있으며, 일부는 크기를 줄이거 나, 다른 조합을 사용하거나 확장합니다.

M=np.arange(9).reshape(3,3)
M[:,0].shape # (3,) selects one column, returns a 1d array
M[0,:].shape # same, one row, 1d array
M[:,[0]].shape # (3,1), index with a list (or array), returns 2d
M[:,[0,1]].shape # (3,2)

In [20]: np.dot(M[:,0].reshape(3,1),np.ones((1,3)))

Out[20]: 
array([[ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 6.,  6.,  6.]])

In [21]: np.dot(M[:,[0]],np.ones((1,3)))
Out[21]: 
array([[ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 6.,  6.,  6.]])

동일한 배열을 제공하는 다른 표현식

np.dot(M[:,0][:,np.newaxis],np.ones((1,3)))
np.dot(np.atleast_2d(M[:,0]).T,np.ones((1,3)))
np.einsum('i,j',M[:,0],np.ones((3)))
M1=M[:,0]; R=np.ones((3)); np.dot(M1[:,None], R[None,:])

MATLAB은 2D 배열로 시작했습니다. 최신 버전에서는 더 많은 차원이 허용되지만 하한은 2로 유지됩니다. 그러나 행 행렬과 열의 차이 (형상 (1,3)v 와의 차이)에 여전히주의를 기울여야합니다 (3,1). 얼마나 자주 글을 썼 [1,2,3].'습니까? 나는 쓰기로가는 row vectorcolumn vector하지만 2D 제약 조건, MATLAB에서 어떤 벡터가 없습니다 - 이상하지 1D 인 것으로 벡터의 수학적 의미에서.

당신이 봤어 np.atleast_2d(또한 _1d 및 _3d 버전)?


1

1) (R, 1)오버 형태를 선호하지 않는 이유 (R,)는 불필요하게 복잡하게 만들기 때문입니다. 게다가, (R, 1)길이 -R 벡터 대신에 기본적으로 모양을 갖는 것이 왜 바람직 (1, R)할까요? 추가 치수가 필요할 때 간단하고 명시 적으로 유지하는 것이 좋습니다.

2) 예를 들어 외부 제품을 계산하므로 다음 reshape을 사용하여 전화 하지 않고이 작업을 수행 할 수 있습니다 np.outer.

np.outer(M[:,0], numpy.ones((1, R)))

답변 해주셔서 감사합니다. 1은) M[:,0]그것을 가지고 더 의미한다, 그래서 본질적으로, 첫 번째 요소와 모든 행을지고 (R, 1)보다가 (1, R). 2) 항상 ( np.outer예를 들어, 모양 (1, R) 다음에 (R, 1)의 행렬에 대한 점으로 대체 할 수있는 것은 아닙니다 .
clwen

1) 네, 할 수 컨벤션 수 있지만 다른 상황에서 덜 편리합니다. 규칙은 M [1, 1]이 모양 (1, 1) 배열을 반환하는 것일 수도 있지만 일반적으로 스칼라보다 덜 편리합니다. 행렬 같은 행동을 정말로 원한다면 matrix객체 를 사용하는 것이 좋습니다 . 2) 사실 np.outer에 관계없이 형상인지의 작동 (1, R), (R, 1)또는 이들의 조합.
bogatron

0

여기에 이미 많은 좋은 답변이 있습니다. 그러나 나를 위해 모양이나 배열이 모든 프로그램을 중단 할 수있는 몇 가지 예를 찾기가 어려웠습니다.

여기에 하나가 있습니다 :

import numpy as np
a = np.array([1,2,3,4])
b = np.array([10,20,30,40])


from sklearn.linear_model import LinearRegression
regr = LinearRegression()
regr.fit(a,b)

오류와 함께 실패합니다.

ValueError : 예상 2D 배열, 대신 1D 배열을 얻음

그러나 우리가 다음에 추가 reshape하면 a:

a = np.array([1,2,3,4]).reshape(-1,1)

이것은 올바르게 작동합니다!

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