[BigData] Numpy 기본
2023. 3. 13. 21:43ㆍComputer Sciences/BigData
Numpy
행렬이나 대규모 다차원 배열을 쉽게 처리할 수 있도록 지원하는 파이썬 라이브러리이다.
파이썬 리스트 vs 넘파이 어레이
1. 선언 조건
- 파이썬 리스트
- 모든 타입을 가질 수 있다.
- 2차원 이상 배열 구조에서 내부 배열의 원소 개수가 달라도 된다.
- 넘파이 어레이
- 숫자형 또는 문자열만 가질 수 있으며 숫자형과 문자열이 섞이면 모두 문자열로 전환
- 2차원 이상 배열 구조에서 내부 배열의 원소 개수가 같아야 한다.
# 파이썬 리스트
a = [1, 2, 3, 'four', 'five'] # 1, 2, 3은 number, four five는 string
b = [[1], [2, 3], ['four', 'five']] # 파이썬 리스트는 원소 개수가 달라도 됨
# 넘파이 어레이
import numpy as np
arr = [1, 2, 3, 'four', 'five']
a = np.array(arr) # 1, 2, 3이 모두 문자열로 전환됨
b = np.array([[1, 2], [3, 4], [5, 6]]) # 넘파이 어레이는 원소 개수가 같아야 함
2. 연산
- 파이썬 리스트는 덧셈 연산 시 항목을 이어 붙이는 concatenate 수행
- 또한 리스트 간 다른 연산은 허용하지 않음
- 곱셈은 자연수 곱셈만 가능, 원소 복사를 의미
a = [1, 3, 5]
b = [2, 4, 6]
a + b # [1, 3, 5, 2, 4, 6]
# 곱하기, 빼기, 나누기 불가능
a * 3 # [1, 3, 5, 1, 3, 5, 1, 3, 5]
- 넘파이 어레이는 덧셈 시 항목 간 덧셈을 수행, 다른 사칙연산도 동일
- 실수에 대한 사칙연산 과정도 원소 전체의 값에 대하여 수행 가능
a = np.array([1, 3, 5])
b = np.array([2, 4, 6])
a + b # [3, 7, 11]
a * b # [2, 12, 30]
a + 2 # [3, 5, 7]
a * 3 # [3, 9, 15]
3. 메소드
- 두 자료구조에서 다루는 자료형이 다르기 때문에 지원하는 메소드도 다름
- 파이썬 리스트에서는 mean, argmax, round 등 넘파이 어레이 메소드 지원 X
- 넘파이 어레이에서는 append, remove, extend 등 파이썬 리스트 메소드 지원 X
4. 연산 속도
같은 연산을 수행하는 경우 넘파이 어레이가 훨씬 빠르다.
사용법
Array 생성
# numpy 라이브러리 임포트
import numpy as np
# numpy 배열 생성
l = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
na = np.array(l)
# [[0 1 2]
# [3 4 5]
# [6 7 8]
# [9 10 11]]
# 범위 지정해서 생성
narg = np.arange(0, 12, 1) # 0부터 12까지 1 단위로 생성
print(narg) # [0 1 2 3 4 5 6 7 8 9 10 11]
# 0으로 초기화해서 생성
naz = np.zeros((4, 3))
# [[0 0 0]
# [0 0 0]
# [0 0 0]
# [0 0 0]]
# 특정 array와 동일한 shape로 생성
nas = np.zeros(na.shape)
nas = np.zeros_like(na)
# [[0 0 0]
# [0 0 0]
# [0 0 0]
# [0 0 0]]
Array 채우기
# numpy 라이브러리 임포트
import numpy as np
# 특정 값으로 채우기
nas.fill(1)
# [[1 1 1]
# [1 1 1]
# [1 1 1]
# [1 1 1]]
# 특정 값 할당
nas[:] = 2
# [[2 2 2]
# [2 2 2]
# [2 2 2]
# [2 2 2]]
# 특정 배열을 특정 모양으로 반복하여 할당
a = np.array([1, 2])
np.tile(a, 3)
# [1 2 1 2 1 2]
np.tile(a, (2, 2))
# [[1 2 1 2]
# [1 2 1 2]]
Array 구조 변경
# numpy 라이브러리 임포트
import numpy as np
# 연산자의 replace/in-place 여부를 꼭 확인해야 함
# reshape는 replace가 아님
xrn = np.arange(0, 12, 1)
xrn.reshape(4, 3) # 원본은 변경되지 않음
print(xrn)
# [0 1 2 3 4 5 6 7 8 9 10 11 12]
xrn = xrn.reshape(4, 3) # 재할당으로 변경
print(xrn)
# [[0 1 2]
# [3 4 5]
# [6 7 8]
# [9 10 11]]
# reshape의 마지막 파라미터는 -1도 가능하며 이 경우 자동으로 설정된다.
# 아래의 경우 12개의 원소를 4행으로 만드므로 (4, 3)의 array가 생성된다.
xs = np.arange(0, 12, 1).reshape(4, -1)
print(xs)
# [[0 1 2]
# [3 4 5]
# [6 7 8]
# [9 10 11]]
# 12개의 원소를 dimension=2, 2행이므로 열은 3으로 자동으로 설정된다.
x = np.arange(0, 12, 1).reshape(2, 2, -1)
print(x)
# [[[0 1 2]
# [3 4 5]]
# [[6 7 8]
# [9 10 11]]]
# 다차원 array를 1차원 array로 평평하게(flat) 변환한다.
xs = x.flatten()
print(xs)
# [0 1 2 3 4 5 6 7 8 9 10 11]
xs = x.reshape(-1)
print(xs)
# [0 1 2 3 4 5 6 7 8 9 10 11]
Slicing, Indexing
import numpy as np
x = np.arange(0, 12, 1).reshape(4, 3)
# 0번째 행의 1, 2번째 요소 슬라이싱
x_slicing = x[0, 1:3]
print(x_slicing)
# [1 2]
# 모든 행의 1, 2번째 요소 슬라이싱
x_slicing = x[:, 1:3]
print(x_slicing)
# [[1 2]
# [4 5]
# [7 8]
# [10 11]
# 0, 2번째 행의 모든 요소 슬라이싱
x_slicing = x[::2, :]
print(x_slicing)
# [[0 1 2]
# [6 7 8]]
# 0, 2번째 행의 0, 2번째 요소 슬라이싱
x_slicing = x[::2, ::2]
print(x_slicing)
# [[0 2]
# [6 8]]
# 모든 요소 슬라이싱
x_slicing = x[:]
x_slicing = x[:,:]
print(x_slicing)
# [[0 1 2]
# [3 4 5]
# [6 7 8]
# [9 10 11]]
Masking
import numpy as np
x = np.arange(0, 12, 1).reshape(4, 3)
# 요소의 값이 4보다 큰 경우 해당 요소는 true,
# 작은 경우 false로 하는 같은 shape의 array 반환
x_mask = x > 4
print(x_mask)
# [[False False False]
# [False False True]
# [True True True]
# [True True True]]
# x에서 x_mask가 True인 값들로 이루어진 1차원 array 반환
x_masking = x[x_mask]
print(x_masking)
# [5 6 7 8 9 10 11]
Broadcasting
import numpy as np
x = np.arange(0, 12, 1).reshape(4, 3)
add = x + 3
print(add)
# [[3 4 5]
# [6 7 8]
# [9 10 11]
# [12 13 14]]
mul = x * 3
# [[0 3 6]
# [9 12 15]
# [18 21 24]
# [27 30 33]]
x1 = np.arange(0, 4, 1)
# [0 1 2 3]
x2 = np.arange(1, 3, 1)
# [1 2]
x3 = x1 * x2
# shape 문제로 브로드캐스팅 불가
#
x2r = x2.reshape(2, 1)
# [[1]
# [2]]
# dimension이 다른 경우 큰 쪽에 맞춰짐
x4 = x1 * x2r
# [[0 1 2 3]
# [0 2 4 6]]
x5 = np.array([3])
x6 = x1 * x5
# [0 3 6 9]
행렬곱
import numpy as np
a = np.arange(1, 5).reshape(2, 2)
# [[1 2]
# [3 4]]
b = np.arange(6, 10).reshape(2, 2)
# [[6 7]
# [8 9]]
c = a * b
d = np.dot(a, b)
# [[6 14]
# [24 36]]
Reduction
import numpy as np
x = np.arange(0, 12, 1).reshape(4, 3)
# 축을 모두 없애고 평균을 구해서 반환
xm = x.mean()
xm = np.mean(x)
# 5.5
# 열 평균 - axis=0
xc = x.mean(axis=0)
# [4.5 5.5 6.5]
# 행 평균 - axis=1
xr = x.mean(axis=1)
# [1 4 7 10]
Fortran-style order
import numpy as np
xf = np.arange(0, 12, 1).reshape(4, 3, order='F')
# [[0 4 8]
# [1 5 9]
# [2 6 10]
# [3 7 11]]
Concatenation
import numpy as np
x = np.arange(0, 12, 1).reshape(4, 3)
y = np.arange(12, 24, 1).reshape(4, 3)
# 열 기준으로 concat
np.concatenate([x, y], axis=0)
# [[0 1 2]
# [3 4 5]
# [6 7 8]
# [9 10 11]
# [12 13 14]
# [15 16 17]
# [18 19 20]
# [21 22 23]]
# 행 기준으로 concat
np.concatenate([x, y], axis=1)
# [[0 1 2 12 13 14]
# [3 4 5 15 16 17]
# [6 7 8 18 19 20]
# [9 10 11 21 22 23]]
x1 = np.arange(0, 3, 1)
y1 = np.arange(3, 6, 1)
np.concatenate([x1, y1], axis=0)
# [0 1 2 3 4 5]
Copies and views
import numpy as np
# 복사본(copy)은 어떤 변경을 하더라도 원본에 영향을 끼치지 않는다.
arr = np.array([1, 2, 3, 4, 5])
copy = arr.copy()
arr[0] = 21
print(arr)
# [21 2 3 4 5]
print(copy)
# [1 2 3 4 5]
# 뷰(view)는 변경 시 원본에도 영향을 끼친다.
arr = np.array([1, 2, 3, 4, 5])
view = arr.view()
arr[0] = 32
print(arr)
# [32 2 3 4 5]
print(view)
# [32 2 3 4 5]
# original이나 copy는 다른 객체로부터 생성된 것이 아닌 base object
# view는 다른 객체로부터 생성된 것으로 view의 base object는 original array
arr = np.array([1, 2, 3, 4, 5])
print(arr.base)
# None
copy = arr.copy()
print(copy.base)
# None
print(copy.base is arr)
# False
view = arr.view()
print(view.base)
# [1 2 3 4 5]
print(view.base is arr)
# True
'Computer Sciences > BigData' 카테고리의 다른 글
[BigData] 데이터 시각화 (0) | 2023.04.17 |
---|---|
[BigData] 데이터 정규화 (0) | 2023.04.17 |
[BigData] 데이터 이해 (1) | 2023.04.17 |
[BigData] Pandas 기본 (4) | 2023.03.14 |