빅데이터 분석
Numpy
CMS419
2021. 10. 4. 13:40
Numpy
- 숫자 배열을 효과 적으로 저장하고 가공하는 전문도구
- 파이썬 데이터 과학 도구 생태계의 핵심
- Numpy 배열을 연속된 메모리 블록에 데이터를 저장한다.
- 벡터화 연산 : 루프 없이 데이터 처리 작업이 가능하다
ndarray 배열 생성
np.array() 함수를 써서, 배열을 생성한다.
np.zeros(10, dtype=int) #0으로 채운 배열
np.ones((3,5), dtype=float) #1로 채운 배열
np.full((3,5), 3.14) #같은 값으로 채운 배열
np.arange(0, 20, 2) #선형 수열로 채운 배열(step), range()와 유사
np.linspace(0, 1, 5) #일정한 간격으로 채운 배열(개수)
np.random.seed(0) #재현을 위한 씨드값
np.random.random((3,3)) #[0,1)난수로 채운 배열
np.random.normal(0, 1, (3,3)) #정규분포 난수로 채운 배열
np.random.randint(0, 10, (3,3)) #정수 난수로 채운 배열 [low, high)
np.eye(3) #항등행렬(identity matrix)
np.empty(3) #초기화되지 않은 배열(메모리에 남아 있는 값)
배열 인덱싱
단일 원소(특정 원소)에 접근하는 법
다차원 배열에서는 콤마로 구분된 인덱스 튜플 사용
x[2]
x[-1]
y[0, 0]
y[1, 2] = 100
배열 슬라이싱(slicing) : 부분배열(subarray)에 접근하기
x[start:stop:step] #디폴트 start=0, stop=차원크기, step=1
- 배열 슬라이스는 원래 배열의 사본(copy)이 아니라 뷰(view)를 반환하므로 슬라이스를 수정하면 원래 배열이 변경된다.
- 데이터를 명시적으로 복사하고 싶으면, copy() 메서드 사용
reshape() 매서드
1차원 배열을 2차원 행렬로 전환할 수 있다.
z = np.array([1,2,3]) #1차원 배열
z.reshape((1,3)) #z[np.newaxis, :]와 동일
z.reshape((3,1)) #z[:, np.newaxis]와 동일
배열 연결
np.concatenate 함수 : array 리스트를 인수 한다.
x = np.array([1,2,3])
y = np.array([3,2,1])
np.concatenate([x, y]) #x+y는 원소별 합
grid = np.array([[4,5,6], [7,8,9]])
np.concatenate([grid, grid]) #행(axis=0)결합
np.concatenate([grid, grid], axis = 1) #열(axis=1)결합
np.vstack & np.hstack 함수 : array 리스트를 인수로 함
np.vstack([x,grid]) #수직으로 쌓기
z = np.array([[99],[99]])
np.hstack([grid, z]) #수평으로 쌓기
np.r_ & np.c_ 루틴 : 배열을 행(열)로 연결
a = np.full((2,2), 1)
b = np.full((2,2), 2)
np.r_[a,b] #수평으로 쌓기
np.c_[a,b] #수직으로 쌓기
배열 분할
np.split, np.hsplit, np.vsplit 함수로 구현
x = [1,2,3,99,99,3,2,1]
x1, x2, x3 = np.split(x, [3,5])
grid = np.arange(16).reshape((4, 4))
upper, lower = np.vsplit(grid, [2])
left, right = np.hsplit(grid, [2])
백터화 연산
백터화 연산은 루프 없이 배열의 각 요소에 연산을 적용한다.
구현
- 유니버설 함수(UFuncs : universal functions)
- 브로드캐스팅(broadcasting)
NumPy UFuncs
- 배열의 각 원소(element)에 유니버설 함수를 적용
- 산술 연산자는 NumPy의 ufunc로 구현 ex) a + b ⇔ np.add(a, b)
- 유니버설 수학 함수 : np.abs(), np,sin(), np.exp(), np.log(), np.power(), ... 등이 있다.
브로드캐스팅
차원이 다른 두 배열의 연산을 확장하는 방식
차원이 더 큰 배열에 맞춰 더 작은 차원의 배열의 shape을 확장
np.arange(3) + 5
np.ones((3,3)) + np.arange(3)
np.arange(3).reshape(3,1) + np.arange(3)
np.ones((3,2)) + np.arange(3) #ValueError : 브로드캐스트 불가
인터넷에 좋은 이미지들이 많다.
배열 집계
Numpy 함수가 빠르다.
브로드캐스팅 & 집계 예제
- 데이터 표준화(standardization)
- 데이터 센터링(centering) : 각 열의 평균을 빼기
- 데이터 스케일링(scaling) : 각 열의 표준편차로 나누기
비교, 마스크, 부울 로직
비교
비교 연산자도 NumPy의 ufunc로 구현 ex) x < 3 ⇔ np.less(x, 3)
비교 연산자 : ==, !=, <, <=, >, >=
연산 결과는 부울 타입의 배열
x = np.array([1,2,3,4,5])
x < 3
(2 * x) == (x ** 2)
조건식 : np.where(조건, x, y)
a = np.arange(10)
np.where(a < 5, a, 10*a)
부울 마스킹(masking)
- 특정 기준에 따라 배열을 값을 추출하거나, 수정, 계산, 조작할 때 사용
- 마스킹 연산 : 부울 배열을 인덱스로 사용하여 배열에서 조건에 맞는 값을 선택
x[x<3]
팬시 인덱싱(fancy indexing)
- 팬시 인덱싱 : 단일 스칼라 대신 인덱스 배열을 전달
- 원래 배열을 복사해 처리하므로 값을 변경해도 원래 배열의 값은 변경되지 않음
rand = np.random.RandomState(1)
x = rand.randint(10, size=10) #array([5,8,9,5,0,0,1,7,6,9])
ind = [3, 7, 4]
x[ind] #array([5,7,0])
M = np.arange(12).reshape((3,4))
row = np.array([0,1,2])
col = np.array([2,1,3])
M[row, col]
벡터/행렬 곱
벡터의 외적 vs 내적
x = np.arange(3)
y = np.full(3,1)
np.outer(x, x) #외적
np.inner(x, x) #내적 <=> np.dot(x, x)
np.outer(x, y) #외적
np.inner(x, y) #내적
행렬 곱셈 : dot product 연산(함수) 혹은 @ 연산자
a = np.array([[0,1],[2,3]], float)
b = np.array([2,3], float)
c = np.array([[1,1],[4,0]], float)
np.dot(a, b) # a @ b <=> a.dot(b)
np.dot(a, c) # a @ c <=> a.dot(c)