기본 콘텐츠로 건너뛰기

통계관련 함수와 메서드 사전

A B C d E F G H I K L M N O P Q R S T U V W Z A statsmodels.ap.stats.anova_lm(x) statsmodels.formula.api.ols 에 의해 생성되는 모형 즉, 클래스 인스턴스(x)를 인수로 받아 anova를 실행합니다. np.argsort(x, axis=-1, kind=None) 객체 x를 정렬할 경우 각 값에 대응하는 인덱스를 반환합니다. Axis는 기준 축을 지정하기 위한 매개변수로서 정렬의 방향을 조정할 수 있음(-1은 기본값으로 마지막 축) pandas.Series.autocorr(lag=1) lag에 전달한 지연수에 따른 값들 사이의 자기상관을 계산 B scipy.stats.bernoulli(x, p) 베르누이분포에 관련된 통계량을 계산하기 위한 클래스를 생성합니다. x: 랜덤변수 p: 단일 시행에서의 확률 scipy.stats.binom(x, n, p) 이항분포에 관련된 통계량을 계산하기 위한 클래스를 생성합니다. x: 랜덤변수 n: 총 시행횟수 p: 단일 시행에서의 확률 C scipy.stats.chi2.pdf(x, df, loc=0, scale=1) 카이제곱분포의 확률밀도함수를 계산 $$f(x, k) =\frac{1}{2^{\frac{k}{2}−1}Γ(\frac{k}{2})}x^{k−1}\exp\left(−\frac{x^2}{2}\right)$$ x: 확률변수 df: 자유도 pd.concat(objs, axis=0, join=’outer’, …) 두 개이상의 객체를 결합한 새로운 객체를 반환. objs: Series, DataFrame 객체. Axis=0은 행단위 즉, 열 방향으로 결합, Axis=1은 열단위 즉, 행 방향으

배열(Numpy. array)

내용

  1. 기본 배열의 생성
    1. 배열의 차원과 모양
  2. 배열 생성을 위한 다른 함수
  3. 랜덤수 생성을 위한 함수들
  4. 배열 객체의 자료형
  5. 배열 객체의 인덱스
  6. 배열의 차원 수정
  7. 배열 결합(concatenate)
  8. 배열의 분할

배열(Numpy.array)

배열은 ndarray이라고도 하는데 이 용어는 N-dimensional array의 약어로서 여러개의 값들을 구조적으로 나타낼 수 있는 numpy 라이브러리 기본 데이터형입니다. 다음과 같은 특성을 가집니다.

  1. 리터럴(literal, row data)에 대한 정보, 요소(element)를 찾는 방법 및 요소를 해석하는 방법을 포함합니다.
  2. 배열 내에 각 요소들은 인덱스(index)라고 하는 음이 아닌 정수형태의 특정한 번호를 가집니다.
  3. 모든 요소는 동일한 유형이어야 합니다.
  4. 배열은 여러 차원으로 구성할 수 있으며 차원을 ndim속성으로 확인할 수 있습니다.
  5. 배열의 모양은 각 차원의 수를 표시한 것으로 shape속성으로 확인 할 수 있습니다.

기본 배열의 생성

배열의 차원과 모양

numpy 배열 객체의 생성은 기본적으로 np.array()함수를 사용합니다. 자료형은 dtype등의 속성을 사용하여 확인 또는 지정 할 수 있습니다.

  • np.array(객체, dtype=None)
    • 인수는 리스트형입니다.
    • 인수 dtype에 형식을 지정하여 각 요소들의 자료형을 지정할 수 있습니다.

다음은 1차원 배열을 생성하기 위해 리스트 형식인 [1, 2, 3]을 np.array()함수에 전달한 것입니다.

import numpy as np
a = np.array([1, 2, 3])
a  #(1)
array([1, 2, 3])
print(a) #(2)
[1 2 3]

위 코드 (1)과 같이 객체를 반환하면 배열(array)가 명시되는데 반해 다음 코드(2)와 같이 print()함수에 의한 출력은 단지 내용만을 반환합니다.

배열을 생성과 동시에 각 요소는 음이 아닌 정수 즉, 0부터 시작하는 정수인 고유값이 자동으로 할당되는데 이를 인덱스(index)라고 합니다. 배열 객체를 테이블 형태로 나타내면 인덱스는 각 요소에 지정된 명칭으로 간주할 수 있습니다. 위 객체 a를 표로 나타내면 다음과 같습니다.

인덱스(샘플)
np.array([1, 2, 3]) →  0 1
1 2
2 3

일반적으로 데이터 분석을 위한 표의 경우 행(row)은 샘플(sample)또는 인스턴스(instance), 열(column)을 변수 또는 특성(feature)로 나타냅니다. 그러므로 위 객체 a는 샘플이 3개이고 1개의 변수를 가진다고 할 수 있습니다. 이 구조는 다음 그림과 같이 나타낼 수 있습니다.

객체 a는 위 그림과 같이 필요한 축의 수는 1개입니다. 이것은 다음 코드의 객체의 차원을 반환하는 배열 객체의 속성(attribute) ndim의 결과와 같습니다. 결과적으로 배열 객체를 표현하기 위해 필요한 축의 수가 그 객체의 차원이 됩니다.

파이썬에서 객체는 그 자체가 다양한 메서드, 속성등을 포함하고 있는 함수입니다. 이러한 기능들은 내장함수 dir()로 확인할 수 있습니다. 배열객체의 경우 ndim, shape, size의 속성을 포함하며 각각 객체의 차원, 모양, 객체내의 모든 요소들의 수를 나타내는 크기를 반환합니다.

print(dir(a))
[..., 'ndim', ..., 'shape', 'size', ...]
a.ndim
1
a.shape
(3,)
a.size
3

다음 객체 x는 리스트내에 두 개의 리스트를 포함하고 있는 구조입니다.

x=np.array([[1, 2, 3], [4,5,6]])
print(x)
[[1 2 3]
 [4 5 6]]

위 객체 x를 표로 작성해 보면 다음과 같습니다.

인덱스(샘플)\변수명 0 1 2
0 1 2 3
1 4 5 6

위 객체는 다음 그림과 같이 샘플(인덱스) 축과 변수(특성) 축에 대응하는 각 요소를 나타낼 수 있습니다. 즉, 위 객체를 표시하기 위해서는 2개의 축이 필요합니다. 그러므로 객체 x는 2차원입니다.

plt.scatter(np.repeat(0, 3), [0, 1, 2],s=x[0,:]*100)
plt.scatter(np.repeat(1, 3), [0, 1, 2],s=x[1,:]*100)
plt.xticks([0, 1])
plt.yticks([0, 1, 2])
plt.xlabel("sample", size=12, weight="bold")
plt.ylabel("feature", size=12, weight="bold")
plt.show()
x.ndim
2
x.shape
(2, 3)
x.size
6
객체의 차원은 객체의 각 값을 나타내기 위해 필요한 축의 수이며 이것은 객체에 전달하는 리스트 객체에서 최초 시작되는 여는 대괄호([)의 수와 같습니다.

데이터 과학에서 1차원 배열을 벡터(vector), 2차원을 행렬(matrix), 3차원 이상의 배열을 텐서(tensor)라고 합니다. 이들은 여러 값들의 그룹으로 그룹의 크기 뿐만 아니라 방향성을 가집니다. 그러나 하나의 값은 방향성을 나타낼 수 없지요. 이것을 스칼라(scalar)라고 합니다.

배열 생성을 위한 다른 함수

배열 생성을 위해 numpy 라이브러리의 array()함수 이외에 특정한 목적을 위해 zero(), one(), empty(), arrange(), linspace()의 함수를 사용할 수 있습니다.

배열의 모든 값이 0과 1인 경우 각각 zeros(), ones()함수를 사용하여 생성할 수 있습니다. 이 두 함수에 전달되는 인수는 생성하는 값의 갯수입니다. 물론 생성하는 배열의 차원에 따라 전달해야 하는 인수의 수가 다릅니다. 예를 들어 다음 코드의 zero1, one1과 같이 1차원 베열의 경우 1개의 정수를 전달하지만 2차원 객체인 zero2, one2의 경우는 2개의 정수 즉 행과 열의 수를 전달해야 합니다. 이 두 함수 뿐만 아니라 numpy에서 배열을 생성하는 모든 함수의 경우 2개이상의 인수를 전달 할 경우는 튜플형식으로 전달합니다.

zero1=np.zeros(3)
zero1
array([0., 0., 0.])
one1=np.ones(3)
one1
array([1., 1., 1.])
zero2=np.zeros((2,2))
zero2
array([[0., 0.],
      [0., 0.]])
one2=np.ones((2,2))
one2
array([[1., 1.],
      [1., 1.]])

empty()함수 역시 배열을 생성하지만 생성시 나타나는 값은 컴퓨터 자체에 발생하는 랜덤값으로 배열의 구조만을 생성할 경우 사용합니다. 생성 후 모든 요소들을 다시 채워야 합니다. 값(요소)들이 지정되지 않기 때문에 배열 생성 속도가 개선된다는 장점이 있습니다.

np.empty(3)
array([1., 1., 1.])
np.empty(2)
array([-5.73021895e-300,  6.93539584e-310])
np.empty((2,2))
array([[1., 1.],
      [1., 1.]])

다음 두 함수는 1차원 배열만을 생성합니다. 그러나 추후에 소개할 reshape()등의 메서드를 통해 다차원으로 변환할 수 있습니다.

파이썬 내장함수인 range()와 같이 일정한 간격의 수열을 생성하기 위해 arange()함수를 사용할 수 있습니다. 이 함수는 특징은 다음과 같습니다.

  • np.arange(시작, 마지막, 간격)
    • 인수 중 시작과 간격은 각각 0과 1의 기본값을 가집니다.
    • 인수를 1개만 전달할 경우 시작과 간격은 0과 1입니다
    • 이 함수에 결과는 마지막 수를 포함하지 않습니다.
    • 모든 실수 영역에서 사용할 수 있습니다.
np.arange(4)
array([0, 1, 2, 3])
np.arange(-1, 1, 0.5)
array([-1. , -0.5,  0. ,  0.5])

np.linspace(시작, 마지막, 갯수)함수를 사용하여 구간 [시작, 마지막)에서 지정한 갯수의 수열을 생성합니다.

np.linspace(0,10,5)
array([ 0. ,  2.5,  5. ,  7.5, 10. ])
np.linspace(-1, 1, 6)
array([-1. , -0.6, -0.2,  0.2,  0.6,  1. ])

랜덤수 생성을 위한 함수들

numpy 라이브러리의 random 클래스하에서 랜덤수를 생성하는 다양한 함수를 제공합니다. 이 결과 역시 배열 객체입니다.

함수내용
np.random.rand(r,c)0 ≤ x<1(=[0, 1)) 사이의 균일 분포(uniform distribution)를 따르는 랜덤수 생성
균일분포라는 것은 지정된 범위에서 각각의 값들이 나올 확률이 동일한 분포를 의미
지정한 차원(행×열)의 배열객체를 반환
np.random.randn(r,c)rand()와 유사한 함수로서 랜덤수 생성은 표준정규분포를 따름
np.random.sample((r,c))[0, 1)지정한 크기(차원)의 랜덤수를 생성
위의 함수들과 달리 인수를 튜플 형식으로 전달
np.random.randint(s,e, (r,c))[s, e)의 범위에서 지정한 크기(차원)의 랜덤수를 생성
* r: 행의 수, c:열의 수, s: 시작 수, e:마지막 수
np.random.rand(2,2)
array([[0.15929645, 0.29190401],
       [0.79410849, 0.39557435]])
np.random.randn(2,2)
array([[-0.86682945,  0.1903874 ],
       [-0.27194554, -1.40526577]])
np.random.sample((2,2))
array([[0.84179387, 0.76751748],
       [0.45750306, 0.63112318]])
np.random.randint(1, 10, 3)
array([4, 4, 5])
np.random.randint(10, 20, (2,3))
array([[17, 10, 16],
       [12, 13, 17]])

배열 객체의 자료형

자료형 (data type)은 입력된 데이터를 위한 메모리의 크기를 확정하기 위한 것입니다. 그러므로 데이터 형(data type)을 명시하지 않은 상태에서 여러 유형이 혼재된 경우 일반적으로 큰 메모리가 소비되는 형태로 자동 지정되지만 경우에 따라서는 메모리 과부하 상태로 인해 자료의 손실이 발생할 수 있습니다. 그러므로 다양한 자료형이 혼재된 경우 명시적으로 데이터 타입을 지정하는 것이 안전합니다.

np.array()함수를 사용하여 배열 객체를 생성할 경우 dtype에 인수를 전달함으로서 배열의 데이터형을 지정할 수 있습니다. 그러나 이 값을 지정하지 않을 경우 그 데이터형은 자동으로 지정되는데 일반적으로 numpy 배열의 기본 데이터 형은 실수형(np.float64)입니다. 이것은 정수형과 실수형이 혼합되어 있을 경우 실수형으로 인식된다는 의미입니다.

x=np.ones(1)
x
array([1.])
x.dtype
dtype('float64')

위 속성 dtype은 객체의 데이터 형을 반환하지만 역으로 그 속성을 사용하여 객체의 데이터 형을 지정할 수 있습니다. 예를 들어 다음 객체 x는 실수(부동소수)로 입력하였지만 객체에 int 32를 지정하여 정수형으로 변환할 수 있습니다.

x=np.ones(1, dtype=np.int32)
x
array([1], dtype=int32)
x.dtype
dtype('int32')

다음 표는 numpy 배열에서 사용할 수 있는 자료형의 종류입니다.

구분 type(code)
숫자형 boolean bool(b) [True, False]
정수형 int8(i1) [-2, 0, 1,2]
int16(i2)
int32(i4)
int64(i8)
unsigned
정수형
uint8(u1) [2, 0, 1,2]
uint16(u2)
uint32(u4)
unt64(u8)
부동소수형 float16(f2) [-2.0, 0.0, 1.0,2.0]
float32(f4)
float64(f8)
복소수형 complex64(c8) (1+2j)
complex128(c16)
문자형 문자형 string(S) ['book','computer', '2', 'a']

다음은 문자열(string)으로 구성된 배열의 자료형입니다.

y=np.array(['a', 'computer'])
y.dtype
dtype('<U8')
y1=np.array(['1'])
y1.dtype
dtype('<U1')

위의 결과중 '<U8'는 유니코드 문자열(Unicode string)로서 최대 문자열의 길이가 8가 미만이라는 것을 의미합니다. 이와같은 자료형의 축약코드는 다음 표와 같습니다.

코드 의미
'b' boolean
'i' (signed) integer
'u' unsigned integer
'f' floating-point
'c' complex-floating point
'm' timedelta
'M' timedelta
'O' (Python) objects
'S', 'a' (Python) objects
'O' zero-terminated bytes (not recommended)
'U' Unicode string
'V' raw data (void)

객체 y1은 숫자형으로 전환될 수 있는 문자형입니다. 형변환은 astype()메서드를 사용합니다.

y2=y1.astype(np.int64)
y2
array([1])
y2.dtype
dtype('int64')

np.dtype.kind 속성을 사용하여 객체의 자료형을 나타낼 수 있습니다.

x=np.array([0b1010])
x.dtype.kind
'i'
from numpy import random
x=np.random.rand(3)
x
array([0.98534827, 0.59160359, 0.14627715])
x.dtype
dtype('float64')
x.dtype.kind
'f'
y=np.array([True, False])
y.dtype
dtype('bool')
y.dtype.kind
'b'

배열 객체의 인덱스

파이썬의 리스트 객체는 요소들의 순서가 정해진 시퀀스 객체로서, 포함되어 있는 각 요소에 0부터 시작하는 정수인 인덱스가 부여됩니다. 리스트 객체를 인수로 받아 형성되는 배열 역시 각 요소는 인덱스를 가집니다. 이러한 인덱스를 사용하여 배열의 부분을 분취할 수 있습니다. 이러한 과정을 슬라이싱(slicing)이라고 하며 이를 통해 요소들을 삭제, 수정, 첨가등의 다양한 조정이 가능합니다.

그림 1, 2에서 나타낸 것과 같이 각 값을 특정할 수 있는 축은 1차원에서 1개, 2차원에서 2개입니다. 이것은 각 요소의 인덱스로 작용합니다. 결과적으로 배열의 각 요소에 대한 인덱스의 수는 차원의 수와 같습니다. 예를 들어 다음 객체 arr은 1차원 배열로서 각 요소의 인덱스는 최초 0에서 5까지 부여됩니다. 객체에서의 인덱스는 다음과 같이 대괄호를 사용합니다.

객체이름.[인덱스]

다음 객체 arr은 1차원 배열 객체입니다. 즉, 각 요소를 나타내기 위해 사용되는 축의 수는 1이므로 각 요소의 인덱스의 수 역시 1개입니다.

lst=[1,2,3,4,5,6]
arr=np.array(lst)
print(arr)
[1 2 3 4 5 6]
for i in range(6):
    print(arr[i])
1
  2
  3
  4
  5
  6

다음의 2차원 배열인 객체 arr2은 각 값을 특정하기 위해 다음 표와 같이 행방향과 열방향의 인덱스가 필요합니다.

a=[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
arr2=np.array(a)
print(arr2)
[[ 1  2  3  4]
   [ 5  6  7  8]
   [ 9 10 11 12]]
arr2.ndim
2
표. 2차원 배열의 인덱스
  열인덱스
행 인덱스
0 1 2 3
0 1 2 3 4
1 5 6 7 8
2 9 10 11 12

위 객체 arr2의 인덱스는 [행, 열]과 같이 두개의 인자를 전달되어야 합니다. 인덱스를 사용하여 모든 요소를 호출하기 위해 반복문.shape 속성을 적용합니다.

arr2[0,0]
1
r, c=arr2.shape
r, c
(3, 4)
for i in range(r):
 for j in range(c):
  print(arr2[i, j])
1
  2
  ⋮
  11
  12

인덱스에서 음의 정수는 inverse(역)을 의미합니다. 인덱스 -1이라면 배열의 마지막에서 첫번째를 의미합니다. 이외에도 인덱스를 사용하는 몇가지 방법이 존재하며 다음과 같습니다.

[정수]또는 [정수, :] 지정한 수의 행 전체
[:, 정수] 지정한 열이 전체
[정수1, 정수2] 지정한 행(정수1)과 열(정수2)
[:, :] 모든 요소들
[음의 정수1, 음의정수2] 배열을 마지막 요소부터 고려
arr2[0]
array([1, 2, 3, 4])
arr2[:,0]
array([1, 5, 9])
arr2[1,3]
8
arr2[:,:]
array([[ 1,  2,  3,  4],
     [ 5,  6,  7,  8],
     [ 9, 10, 11, 12]])
arr2[-1,-1]
12

다음과 같이 인덱스를 사용하여 지정한 부분을 슬라이싱 할 수 있습니다.

객체[시작: 마지막: 간격]

예를 들어 [::-1]인 경우 배열내의 모든 요소들을 마지막을 시작으로 1씩 감소시켜 슬라이싱합니다. 결과적으로 역전된 배열을 반환합니다. 또한 아래 코드의 [::2]은 배열의 처음부터 2의 간격에 해당하는 요소를 슬라이싱합니다.

x=np.array([9, 2, 1, 3, 8, 3, 6, 7])
x
array([9, 2, 1, 3, 8, 3, 6, 7])
x[::-1]
array([7, 6, 3, 8, 3, 1, 2, 9])
x[::2]
array([9, 1, 8, 6])

위와 같은 슬라이싱을 2차원 이상에 적용하기 위해서는 인자 각각에 적용합니다. 예로서 2차원일 경우 행과 열에 각각 적용해야 합니다.

x=np.random.randint(10, size=(2,2))
x
array([[3, 8],
     [0, 5]])
x[::-1, :]
array([[0, 5],
     [3, 8]])
x[:,::-1]
array([[8, 3],
     [5, 0]])
x[::-1,::-1]
array([[5, 0],
     [8, 3]])

슬라이싱을 위해 정수와 콜론(:)을 사용하는 방법 외에 불리언 (boolean)으로 실행 할 수 있습니다.

x=np.random.randint(30, size=(10))
x
array([29,  6,  3,  0, 24, 17, 22, 26, 16, 19])
x%3==0
array([False,  True,  True,  True,  True, False, False, False, False,
       False])
x[x%3==0]
array([ 6,  3,  0, 24])

다음은 위 배열 객체에서 슬라이싱 된 부분의 값을 수정하는 과정입니다.

x=np.random.randint(10, size=(2, 3))
x
array([[7, 5, 0],
     [8, 9, 8]])
x[x%3==0]=x[x%3==0]+10
x
array([[ 7,  5, 10],
     [ 8, 19,  8]])

배열의 차원 수정

배열의 차원을 수정하기 위해 reshape()함수 또는 메서드 나 flatten(), ravel()메서드, newaxis의 속성을 사용할 수 있습니다.

  • np.reshape(객체, shape), 객체.reshape(shape)
    • 객체를 지정한 배열의 모양(shape)으로 변환
    • 2차원 배열의 경우 인수 중 하나를 고정하고 다른 인수로 -1을 전달할 경우 자동으로 배분
x=np.random.randint(20, size=(3,4))
x
array([[ 6,  3,  8,  8],
     [13,  5,  7,  9],
     [ 9,  0,  7,  8]])
print(x.reshape((2,6)))
[[ 6  3  8  8 13  5]
   [ 7  9  9  0  7  8]]
print(np.reshape(x, (-1, 6)))
[[ 6  3  8  8 13  5]
   [ 7  9  9  0  7  8]]
print(x.reshape((6,-1)))
[[ 6  3]
   [ 8  8]
   [13  5]
   [ 7  9]
   [ 9  0]
   [ 7  8]]
print(x.reshape((4,3)))
[[ 6  3  8]
   [ 8 13  5]
   [ 7  9  9]
   [ 0  7  8]]

다음 flatten()ravel()메서드는 다차원 배열을 1차원으로 전환합니다.

x.flatten()
array([ 6,  3,  8,  8, 13,  5,  7,  9,  9,  0,  7,  8])
x.ravel()
array([ 6,  3,  8,  8, 13,  5,  7,  9,  9,  0,  7,  8])

배열에 포함된 부분요소 또는 그 배열 자체의 차원을 증가시키기 위해서는 np.newaxis 메서드를 적용합니다.

객체[part 또는 all, np.newaxis]
y=np.random.randint(10, size=(3))
y
array([5, 9, 2]) #벡터
y[1]
9 #스칼라
y[1].ndim
0 #스칼라

위 코드의 1차원 배열인 y에서 y[1]과 같이 요소 하나를 슬라이싱하면 차원이 0인 스칼라가 됩니다. 그러나 다음 코드의 ①과 같이 시행하여 y의 부분은 y[1]의 차원을 증가시킬 수 있습니다. 실제로 스칼라 즉, 0차원이 1차원으로 증가된 것을 알 수 있습니다. ②은 y 자체를 1차원 증가시켜 2차원으로 변환한 것입니다.

y[1, np.newaxis]  # ①
array([9])
y[1, np.newaxis].ndim
1
y[:, np.newaxis] # ②
array([[5],
     [9],
     [2]]) #2차원 행렬
y[:, np.newaxis].ndim
2

다음은 2차원 배열인 x에 np.newaxis를 적용한 것으로 위 객체 y에 적용한 것과 같은 방법이 사용됩니다.

x=np.random.randint(10, size=(2,2))
x
array([[4, 6],
     [5, 7]])
x[:,:,np.newaxis] 
array([[[4],
     [6]],
     [[5],
     [7]]])
x[:, 1, np.newaxis]
array([[6],
     [7]])
x[1,:, np.newaxis]
array([[5],
     [7]])

배열 결합(concatenate)

두 개 이상의 동일한 차원의 배열들을 결합하기 위해 사용할 수 있는 다양한 함수들이 존재합니다. 그러한 함수들 중 concatenate, stack, hstack, vstack, r_, c_, dstack, block등의 함수를 알아봅니다.

  • np.concatenate((x,y,...), axis=0)
    • 인수 axis에 배열들에 존재하는 축들 중의 하나를 지정
    • axis는 shape 결과의 인덱스와 같음. 즉, 그 인덱스 0은 1차원 배열, 1은 2차원 배열등을 의미
    • 존재하지 않은 축을 지정할 경우 예외 발생

다음은 두 1차원 배열(벡터)들을 연결하는 것으로 axis 인자는 0만 존재합니다.

a=np.array([0,7,9])
b=np.array([8,3,5])
print(a)
[0 7 9]
print(b)
[8 3 5]
ab0=np.concatenate((a,b), axis=0)
print(ab0, ab0.shape)
[0 7 9 8 3 5] (6,)
ab1=np.concatenate((a,b), axis=1)
print(ab1, ab1.shape)
AxisError: axis 1 is out of bounds for array of dimension 1

2차원 배열의 경우 axis=0은 행축, 1은 열축을 기준으로 결합합니다. 그러므로 다음의 결과에서 각각 수직과 수평적으로 결합을 나타냅니다.

c=np.random.randint(10, size=(2,3))
print(c, c.shape)
[[1 6 5]
    [9 7 8]] (2, 3)
d=np.random.randint(10, size=(2,3))
print(d, d.shape)
[[9 6 3]
    [1 2 6]] (2, 3)
e=np.random.randint(10, size=(2,3))
print(e, e.shape)
[[8 6 7]
    [6 4 0]] (2, 3)
cde1=np.concatenate([c, d, e], axis=1)
print(cde1, cde1.shape)
[[1 6 5 9 6 3 8 6 7]
    [9 7 8 1 2 6 6 4 0]] (2, 9)
cde=np.concatenate([c, d, e], axis=0)
print(cde, cde.shape)
[[1 6 5]
    [9 7 8]
    [9 6 3]
    [1 2 6]
    [8 6 7]
    [6 4 0]] (6, 3)
  • np.stack((x,y,...), axis=0)
    • 함수에 전달된 각 배열의 축은 한개가 증가 됨, x, y가 1차원인 경우 함수에 전달된 경우 2차원으로 변경되어 결합시작
    • 각 객체에 추가된 축들의 결합
    • 인수 axis는 결과 배열의 축을 지정
    • axis=0인 경우 결과에서 새롭게 생성되는 축은 첫축이 됨(기본값)
    • axis=-1은 새축은 마지막 축이 됨

1차원인 두 벡터에 np.stack()를 적용하면 다음과 같습니다.

a=np.random.randint(0, 10, 2)
b=np.random.randint(0, 10, 2)
a, b
(array([9, 8]), array([2, 3]))

a: 1차원 → 2차원 (1 × 2, 또는 2 × 1 )

b: 1차원 → 2차원 (1 × 2, 또는 2 × 1 )

a+b: 2차원 (2 × 2, 또는 2 × 2 )

axis=0인 경우 a, b각각은 첫 번째 축이 첨가 되므로 1 × 2가 되는 경우 두 객체의 결합은 첫번째 축들의 결합으로 2 × 2이 됩니다.

$$\begin{align}a&=\begin{bmatrix}9&8\end{bmatrix}\\ b&=\begin{bmatrix}2&3\end{bmatrix}\\ a+b&=\begin{bmatrix}9&8\\2&3\end{bmatrix} \end{align}$$
np.stack((a,b), axis=0)
array([[9, 8],
       [2, 3]])

axis=1인 경우 a, b에 두 번째 축이 첨가 되므로 2 × 1가 되는 경우 두 객체의 결합은 두번째 축들의 결합으로 2 × 2이 됩니다.

$$\begin{align}a&=\begin{bmatrix}9\\8\end{bmatrix}\\ b&=\begin{bmatrix}2\\3\end{bmatrix}\\ a+b&=\begin{bmatrix}9&2\\8&3\end{bmatrix} \end{align}$$
np.stack((a, b), axis=1)
array([[9, 2],
       [8, 3]])

다음 코드에서 a, b는 (3,4)의 모양인 2차원 배열이므로 축이 첨가될 부분은 다음과 같이 n1 또는 n2 또는 n3의 위치입니다. 또한 np.stack()의 적용은 추가된 축들을 결합하는 것으로 다음과 같은 차원의 변화를 반환합니다.

  • axis=0: n1위치에 첨가, 1×3×4 + 1×3×4 = 2×3×4
  • axis=1: n2 위치에 첨가, 3×1×4 + 3×1×4 = 3×2×4
  • axis=2 또는 axis=-1: n3 위치에 첨가, 3×4×1 + 3×4×1 = 3×4×2
a=np.random.randint(0, 10, size=(3,4))
b=np.random.randint(0, 10, size=(3,4))
a
array([[9, 8, 4, 3],
       [4, 9, 3, 7],
       [0, 2, 2, 2]])
b
array([[7, 6, 8, 8],
       [1, 1, 8, 3],
       [1, 9, 1, 8]])
#첫번째 축 첨가
a.reshape(1,3,4), b.reshape(1,3,4)
(array([[[9, 8, 4, 3],
         [4, 9, 3, 7],
         [0, 2, 2, 2]]]),
 array([[[7, 6, 8, 8],
         [1, 1, 8, 3],
         [1, 9, 1, 8]]]))
c1=np.stack((a, b), axis=0) 
c1
array([[[9, 8, 4, 3],
        [4, 9, 3, 7],
        [0, 2, 2, 2]],

       [[7, 6, 8, 8],
        [1, 1, 8, 3],
        [1, 9, 1, 8]]])
#두번째 축 첨가
a.reshape(3,1,4), b.reshape(3,1,4)
(array([[[9, 8, 4, 3]],
 
        [[4, 9, 3, 7]],
 
        [[0, 2, 2, 2]]]),
 array([[[7, 6, 8, 8]],
 
        [[1, 1, 8, 3]],
 
        [[1, 9, 1, 8]]]))
c2=np.stack((a, b), axis=1) 
c2
array([[[9, 8, 4, 3],
        [7, 6, 8, 8]],

       [[4, 9, 3, 7],
        [1, 1, 8, 3]],

       [[0, 2, 2, 2],
        [1, 9, 1, 8]]])

3번째 축의 첨가로 객체 a, b는 다음과 같이 변형됩니다.

$$a_{변환}=\begin{bmatrix}\begin{bmatrix}9\\8\\4\\3\end{bmatrix}\begin{bmatrix}4\\9\\3\\7\end{bmatrix}\begin{bmatrix}0\\2\\2\\2\end{bmatrix}\end{bmatrix} \quad b_{변환}=\begin{bmatrix}\begin{bmatrix}7\\6\\8\\8\end{bmatrix}\begin{bmatrix}1\\1\\8\\3\end{bmatrix}\begin{bmatrix}1\\9\\1\\8\end{bmatrix}\end{bmatrix}$$
c3=np.stack((a, b), axis=-1) #= (axis=2)
c3
array([[[9, 7],
        [8, 6],
        [4, 8],
        [3, 8]],

       [[4, 1],
        [9, 1],
        [3, 8],
        [7, 3]],

       [[0, 1],
        [2, 9],
        [2, 1],
        [2, 8]]])
  • np.vstack([x,y,...])
    • 배열내 각 리스트를 수직적으로 연결
    • 인수는 리스트 형식으로 전달
  • hstack([x,y,...])
    • 배열내 각 리스트를 수평적으로 연결
    • 인수는 리스트 형식으로 전달
a=np.random.randint(10, size=(3))
print(a, a.shape)
[7 3 9] (3,)
b=np.random.randint(10, size=(3))
print(b, b.shape)
[5 3 5] (3,)
abv=np.vstack([a, b])
print(abv, abv.shape)
[[7 3 9]
   [5 3 5]] (2, 3)
abh=np.hstack([a, b])
print(abh, abh.shape)
[7 3 9 5 3 5] (6,)

다음은 2차원 배열에 적용한 결과입니다.

c=np.random.randint(10, size=(2,3))
print(c, c.shape)
[[5 6 7]
   [9 3 8]] (2, 3)
d=np.random.randint(10, size=(2,3))
print(d, d.shape)
[[2 4 5]
   [2 5 8]] (2, 3)
cdv=np.vstack([c, d])
print(cdv, cdv.shape)
[[5 6 7]
   [9 3 8]
   [2 4 5]
   [2 5 8]] (4, 3)
cdh=np.hstack([c, d])
print(cdh, cdh.shape)
[[5 6 7 2 4 5]
   [9 3 8 2 5 8]] (2, 6)

다음의 두 함수들은 배열들을 연결하여 vstack()hstack()과 유사한 결과를 나타내지만 벡터들의 다른 결과를 반환합니다.

  • np.r_[x,y,...]
    • 두번째 차원을 수직적으로 결합합니다.
      • (2,3)+(2,3)=(4,3) (=vstack)
    • 1차원 벡터들의 경우 행벡터로 간주하여 처리
      • (3,)→(3, 0), (3,0)+(3,0)=(6,0)
    • 인수는 대괄호 없이 리스트 형식으로 전달
  • np.c_[x,y,...]
    • 첫번째 차원들을 결합
      • (2,3)+(2,3)=(2, 6)(=hstack)
    • 1차원 벡터들의 경우 2차원 배열 객체로 간주
      • (3,)→(3,1), (3,1)+(3,1)=(3,2)
    • 인수는 대괄호 없이 리스트 형식으로 전달
abr=np.r_[a, b]
print(abr, abr.shape)
[7 3 9 5 3 5] (6,)
abc=np.c_[a, b]
print(abc, abc.shape)
[[7 5]
   [3 3]
   [9 5]] (3, 2)
cdr=np.r_[c, d]
print(cdr, cdr.shape)
[[5 6 7]
   [9 3 8]
   [2 4 5]
   [2 5 8]] (4, 3)
cdc=np.c_[c, d]
print(cdc, cdc.shape)
[[5 6 7 2 4 5]
   [9 3 8 2 5 8]] (2, 6)

함수 np.dstack()는 두개 이상의 배열들을 사용하여 최대 3차원배열을 생성합니다.

  • np.dstack((x, y, ...))
    • 1, 2차원 배열들에 각각 새로운 축을 첨가하여 3차원으로 변환
    • 각 배열의 1차 축을 연결
      • (3,)→(1,3,1), (1,3,1)+(1,3,1)=(1,3,2)
      • (2,3)→(2,3,1), (2,3,1)+(2,3,1)=(2,3,2)
a=np.random.randint(10, size=(3))
print(a, a.shape)
[0 7 9] (3,)
b=np.random.randint(10, size=(3))
print(b, b.shape)
[8 3 5] (3,)
ab_d=np.dstack((a,b))
print(ab_d, ab_d.shape)
[[[0 8]
   [7 3]
   [9 5]]] (1, 3, 2)
c=np.random.randint(10, size=(2,3))
print(c, c.shape)
[[7 5 1]
   [4 6 8]] (2, 3)
d=np.random.randint(10, size=(2,3))
print(d, d.shape)
[[0 8 6]
   [6 7 6]] (2, 3)
e=np.random.randint(10, size=(2,3))
print(e, e.shape)
[[2 8 5]
   [0 3 6]] (2, 3)
cd_d=np.dstack([c, d, e])
print(cd_d, cd_d.shape)
[[[7 0 2]
   [5 8 8]
   [1 6 5]]
   [[4 6 0]
   [6 7 3]
   [8 6 6]]] (2, 3, 3)

여러개의 배열들을 하나의 배열로 재구성하기 위해 np.block()함수를 적용할 수 있습니다.

  • np.block([x, y, ...])
    • 동일한 차원의 배열들 또는 브로드캐스팅이 적용되는 배열들 사이에 결합
    • 전달하는 리스트들의 형태에 따라 결과의 차원이 결정
    • np.block([a,b])=np.hstack((a,b))
    • np.block([[a],[b]])=np.vstack((a,b))
a = np.array([1, 2, 3]) 
b = np.array([2, 3, 4]) 
print(np.block([a, b]))
[1 2 3 2 3 4]
print(np.block([[a],[b]]))
[[1 2 3]
   [2 3 4]]
print(np.array([a,b]))
[[1 2 3]
   [2 3 4]]
c=np.random.randint(10, size=(3, 4))
print(c)
[[0 2 3 8]
   [3 7 4 5]
   [1 5 8 5]]
d=np.random.randint(10, size=(3, 4))
print(b)
[[1 6 5 7]
   [9 3 0 6]
   [3 9 6 2]]
print(np.block([c,d]))
[[0, 2, 3, 8, 9, 8, 2, 0],
   [3, 7, 4, 5, 2, 0, 4, 8],
   [1, 5, 8, 5, 3, 7, 0, 7]]
print(np.hstack((c,d)))
[[0, 2, 3, 8, 9, 8, 2, 0],
   [3, 7, 4, 5, 2, 0, 4, 8],
   [1, 5, 8, 5, 3, 7, 0, 7]]
print(np.block([[c],[d]]))
[[0, 2, 3, 8],
   [3, 7, 4, 5],
   [1, 5, 8, 5],
   [9, 8, 2, 0],
   [2, 0, 4, 8],
   [3, 7, 0, 7]]
print(np.vstack([c, d]))
[[0, 2, 3, 8],
   [3, 7, 4, 5],
   [1, 5, 8, 5],
   [9, 8, 2, 0],
   [2, 0, 4, 8],
   [3, 7, 0, 7]]

배열의 분할

하나의 배열을 여러개로 분할하기 위해서는 인덱싱을 사용할 수 있습니다. 대신에 split, hsplit, vsplit, dsplit등의 함수를 사용할 수 있습니다.

  • np.split(배열, 인덱스 또는 정수, axis=0)
    • 배열은 지정한 기준 (인덱스, 또는 정수)에 따라 분할
      • 예로 3(정수): 배열을 지정한 축에 따라 균할 3 등분
      • [2, 4]의 경우 지정한 축이 axis=0이라면 [:2, :], [2:4,:], [4:,:]와 같이 분할
    • axis에 정수 값을 전달하여 축을 지정할 수 있음.
    • .shape의 결과 왼쪽부터 0, 1,...
a = np.arange(10)
print(a)
[0 1 2 3 4 5 6 7 8 9]

분할하는 갯수를 인수로 지정함으로서 균등한 요소 갯수들을 가진 부분들로 분할

print(np.split(a, 5))
[array([0, 1]), array([2, 3]), array([4, 5]), array([6, 7]), array([8, 9])]

객체의 분할 지점으로 인덱스를 지정할 수 있습니다.

print(np.split(a, [2, 6, 7,9]))
[array([0, 1]), array([2, 3, 4, 5]), array([6]), array([7, 8]), array([9])]

위 코드의 [2, 6, 7,9]은 a[:2], a[2:6], a[6:7], a[7:9], a[9:]를 의미합니다.

b=np.random.randint(10, size=(2,3))
print(b, b.shape)
[[9 7 4]
   [9 6 4]] (2, 3)

위 코드의 axis=0이므로 행 기준으로 2등분

np.split(b, 2)
[array([[9, 7, 4]]), array([[9, 6, 4]])]

다음 코드의 axis=1이므로 열 기준으로 3등분. 다음 코드는 좀더 복잡한 모양의 배열의 분할입니다.

np.split(b, 3, axis=1)
[array([[9],
   [9]]),
   array([[7],
   [6]]),
   array([[4],
   [4]])]
c=np.random.randint(10, size=(4,6))
print(c, c.shape)
[[5 4 5 6 0 0]
   [3 2 0 2 1 3]
   [7 0 0 1 5 0]
   [5 1 1 3 4 6]] (4, 6)
np.split(c, [2,3])
[array([[5, 4, 5, 6, 0, 0],
   [3, 2, 0, 2, 1, 3]]),
   array([[7, 0, 0, 1, 5, 0]]),
   array([[5, 1, 1, 3, 4, 6]])]
np.split(c, [2,3], axis=1)
[array([[5, 4],
   [3, 2],
   [7, 0],
   [5, 1]]),
   array([[5],
   [0],
   [0],
   [1]]),
   array([[6, 0, 0],
   [2, 1, 3],
   [1, 5, 0],
   [3, 4, 6]])]

위의 split()함수와 유사하지만 분할되는 축이 지정된 함수들을 사용할 수 있습니다.

  • np.hsplit(배열, 인덱스 또는 정수)
    • 배열의 모양 중 두번째 축을 기준으로 분할, .shape(첫번째축, 두번째축, ...)
    • 2차원 이상의 다차원 배열의 경우 역시 두번째 축이 분할의 기준이 됨
    • 다른 인자는 split()과 같음
  • np.vsplit(배열, 인덱스 또는 정수)
    • 배열의 모양 중 첫번째 축을 기준으로 분할, .shape(첫번째축, 두번째축, ...)
    • 2차원 이상의 다차원 배열의 경우 역시 첫번째 축이 분할의 기준이 됨
    • 다른 인자는 split()과 같음
a = np.arange(16).reshape(4,4)
print(a)
[[ 0  1  2  3]
   [ 4  5  6  7]
   [ 8  9 10 11]
   [12 13 14 15]]
print(np.hsplit(a, 2))
[array([[ 0,  1],
   [ 4,  5],
   [ 8,  9],
   [12, 13]]), array([[ 2,  3],
   [ 6,  7],
   [10, 11],
   [14, 15]])]
print(np.hsplit(a, [2, 3]))
[array([[ 0,  1],
   [ 4,  5],
   [ 8,  9],
   [ 6],
   [10],
   [14]]), array([[ 3],
   [ 7],
   [11],
   [15]])]
b=np.random.randint(10, size=(2,4,2))#(2,4,2)=(2,2,2)+(2,2,2) 
print(b, b.shape)
[[[3 7]
   [9 9]
   [0 2]
   [3 9]]
   [[1 2]
   [6 5]
   [3 5]
   [1 0]]] (2, 4, 2)
np.hsplit(b, 2)
[array([[[3, 7],
   [9, 9]],
   [[1, 2],
   [6, 5]]]),
   array([[[0, 2],
   [3, 9]],
   [[3, 5],
   [1, 0]]])]
a = np.arange(16).reshape(4,4)
print(a)
[[ 0  1  2  3]
    [ 4  5  6  7]
    [ 8  9 10 11]
    [12 13 14 15]]
print(np.vsplit(a, 2))
[array([[0, 1, 2, 3],
          [4, 5, 6, 7]]), array([[ 8,  9, 10, 11],
          [12, 13, 14, 15]])]
print(np.vsplit(a, [2, 3]))
[array([[0, 1, 2, 3],
          [4, 5, 6, 7]]), array([[ 8,  9, 10, 11]]),    array([[12, 13, 14, 15]])]
b=np.random.randint(10, size=(2,4,2))#(2,4,2)=(1,4,2)+(1,4,2) 
print(b, b.shape)
[[[3 7]
     [9 9]
     [0 2]
     [3 9]]
   [[1 2]
     [6 5]
     [3 5]
     [1 0]]] (2, 4, 2)
np.vsplit(b, 2)
[array([[[3, 7],
            [9, 9],
            [0, 2],
            [3, 9]]]),
    array([[[1, 2],
            [6, 5],
            [3, 5],
            [1, 0]]])]

댓글

이 블로그의 인기 게시물

유사변환과 대각화

내용 유사변환 유사행렬의 특성 대각화(Diagonalization) 유사변환(Similarity transformation) 유사변환 n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사하다고 하며 이 변환을 유사 변환 (similarity transformation)이라고 합니다. $$\begin{equation}\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B \end{equation}$$ 식 1의 유사 변환은 다음과 같이 고유값을 적용하여 특성 방정식 형태로 정리할 수 있습니다. $$\begin{align} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align}$$ 위 식의 행렬식은 다음과 같이 정리됩니다. $$\begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \t

matplotlib의 그래프 종류

1. 산포도(scatter plot) plt.scatter(x, y) >>> import matplotlib.pyplot as plt >>> import numpy as np >>> data=np.random.rand(1024, 2) >>> data[:3, :] >>> plt.scatter(data[:,0], data[:,1]) >>> plt.show() 2. 막대그래프(bar chart) plt.bar(x, hight, width, align='center') 매개변수중 width에 인수를 전달하여 막대의 두께를 조절할 수 있다. 또한 align의 인수는 'center'와 'edge' 이다. 기본값은 'center'이다. 이 값은 x축의 레이블이 막대의 중간에 위치(center) 또는 왼쪽 가장자리에 위치(edge)시킨다. 코드에서 np.random.randint 는 특정한 범위내에서 지정한 갯수의 랜덤수를 생성 np.unique(배열, retrun_counts=False, axis=None) : 객체 내의 중복되지 않은 수들을 반환한다. return_counts=True이면 각 수에 대한 빈도수를 반환한다. axis를 통해 행(1), 열(0)을 선택한다. >>> x=np.random.randint(1, 6, size=100) >>> uni,count=np.unique(x, return_counts=True) >>> uni array([1, 2, 3, 4, 5]) >>> count array([25, 17, 23, 16, 19], dtype=int64) >>> plt.bar(uni, count) >>> plt.show() 위의 막대그래프의 막대의

sympy.solvers로 방정식해 구하기

sympy.solvers로 방정식해 구하기 대수 방정식을 해를 계산하기 위해 다음 함수를 사용합니다. sympy.solvers.solve(f, *symbols, **flags) f=0, 즉 동차방정식에 대해 지정한 변수의 해를 계산 f : 식 또는 함수 symbols: 식의 해를 계산하기 위한 변수, 변수가 하나인 경우는 생략가능(자동으로 인식) flags: 계산 또는 결과의 방식을 지정하기 위한 인수들 dict=True: {x:3, y:1}같이 사전형식, 기본값 = False set=True :{(x,3),(y,1)}같이 집합형식, 기본값 = False ratioal=True : 실수를 유리수로 반환, 기본값 = False positive=True: 해들 중에 양수만을 반환, 기본값 = False 예 $x^2=1$의 해를 결정합니다. solve() 함수에 적용하기 위해서는 다음과 같이 식의 한쪽이 0이 되는 형태인 동차식으로 구성되어야 합니다. $$x^2-1=0$$ import numpy as np from sympy import * x = symbols('x') solve(x**2-1, x) [-1, 1] 위 식은 계산 과정은 다음과 같습니다. $$\begin{aligned}x^2-1=0 \rightarrow (x+1)(x-1)=0 \\ x=1 \; \text{or}\; -1\end{aligned}$$ 예 $x^4=1$의 해를 결정합니다. solve() 함수의 인수 set=True를 지정하였으므로 결과는 집합(set)형으로 반환됩니다. eq=x**4-1 solve(eq, set=True) ([x], {(-1,), (-I,), (1,), (I,)}) 위의 경우 I는 복소수입니다.즉 위 결과의 과정은 다음과 같습니다. $$x^4-1=(x^2+1)(x+1)(x-1)=0 \rightarrow x=\pm \sqrt{-1}, \; \pm 1=\pm i,\; \pm1$$ 실수