import numpy as np
import numpy as np
A = np.array([1,2])
B = np.array([4,5])
C = A + B # array([5,7]), 요소별 덧셈
D = A * B # array([4,10]), 요소별 곱셈
E = A**2 # array([1,4]), 모든 요소에 자승
F = A + 2 # array([3,4]), 모든 요소에 덧셈
G = np.sin(A) # array([-0.7568,-0.5440]), 모든 요소에 sin
H = A < 3 # array([True,True]), 모든 요소에 Boolean
I = A[0:2,] # array([1,2])
A *= B # array([4,10]), A = A*B와 동일
NumPy는 수학 함수 np.sin()
, np.cos()
등을 제공한다.
스칼라값을 입력으로 하는 math 패키지와 달리 배열에 대해 elementwise로(즉, 각 요소에 대해) 적용된다.
import numpy as np
x = np.arange(0.,np.pi,1.) # array([0.,1.,2.,3.])
y = np.sin(x) # array([0.,0.8414,0.9092,0.1411])
[Note]
▪ "Universal Function (ufunc)"은
배열의 모든(Universal) 요소에 대해 개별적으로 적용 가능한 함수
예: np.sin(), np.exp(), np.sqrt(), np.add(), np.maximum() 등
import numpy as np
A = np.arange(4).reshape(2,2)
# array([[0,1],
# [2,3]])
B = np.arange(5,5+4).reshape(2,2)
# array([[5,6],
# [7,8]])
# 2차원 배열
# 2행 2열 행렬
# 일반적인 행렬
X = np.arange(2)
# array([0,1])
# 1차원 배열(= 리스트), (2,)
# 길이가 2인 벡터
# 1차원이므로 행/열 개념 없음
Y = np.arange(2).reshape(2,1)
# array([[0],
# [1]])
# 2차원 배열, (2,1)
# 2행 1열 열 벡터
# 세로로 쌓인 값들
Z = np.arange(2).reshape(1,2)
# array([[0,1]])
# 2차원 배열, (1,2)
# 1행 2열 열 벡터
# 가로로 나열된 값들
[Note]
▪ 리스트(list)와 배열(array)의 차이
# A*B
C1 = np.dot(A,B)
C2 = np.matmul(A,B)
C3 = A@B
# 배열 * 배열 = 배열
# C1, C2, C3는 동일한 결과
# 차원: (2,2)*(2,2) = (2,2)
# array([[ 7, 8],
# [31,36]] )
# A*X
X1 = np.dot(A,X)
X2 = np.matmul(A,X)
X3 = A@X
# 배열 * 리스트 = 리스트
# X1, X2, X3는 동일한 결과
# 차원: (2,2)*(2,2) = (2,2)
# array([1,3])
# A*Y
Y1 = np.dot(A,Y)
Y2 = np.matmul(A,Y)
Y3 = A@Y
# 배열 * 배열 = 배열
# Y1, Y2, Y3는 동일한 결과
# 차원: (2,2)*(2*1) = (2,1)
# array([[1],
# [3]])
# A*Z
Z1 = np.dot(A,Z)
Z2 = np.matmul(A,Z)
Z3 = A@Z
# 배열 * 배열 = 배열
# Z1, Z2, Z3는 동일한 결과
# 차원: (2,2)*(1*2) = 행렬 차수 에러
# X*Y
XY = X@Y
# 배열 * 리스트 = 리스트
# 차원: (2,)*(2*1) = (1,)
# array([1])
# 전치행렬(transpose matrix)
A
# array([[0, 1],
# [2, 3]] )
A.T
np.transpose(A)
# array([[0, 2],
# [1, 3]] )
# 선형대수함수
A = np.array([[1,2],[3,7]])
[D,V] = np.linalg.eig(A)
# D = eigenvalues(고유치), V = eigen vectors(고유벡터)
#언팩킹(unpacking): *(asterisk)를 사용
import numpy as np
n = 8
# 잘못된 예: 배열 안에 배열이 들어감
a = np.array([0, 1, np.zeros(n)]) # dtype=object
# 올바른 예: 배열을 평평하게 결합
b = np.array([0, 1, *np.zeros(n)]) # dtype=float64
[Note]
▪ NumPy의 dtype (데이터 타입)
▪ 파이썬의 언팩킹(Unpacking)
import numpy as np
X = np.array( [9.1,8.2,2.3] )
np.amin(X) # 최솟값, 2.3
np.amax(X) # 최댓값, 9.1
np.argmin(X) # 최솟값 위치, 2
np.argmax(X) # 최댓값 위치, 0
np.sort(X) # 오름차순 정렬, array( [2.3,8.2,9.1] )
np.argsort(X) # 오름차순 정렬 위치, array([2, 1, 0], dtype=int64)
np.argsort(X)[0] # 가장 작은 값의 위치, 2
np.argsort(X)[-1] # 가장 큰 값의 위치, 0
np.argsort(X)[-2] # 두 번째로 큰 값의 위치, 1
형태가 다른 행렬의 연산
import numpy as np
A = np.arange(4.).reshape(2,2)
# 2D array, (2,2)
# array( [[0.,1.],
# [2.,3.]] )
X = np.array( [1.,0.] )
# 1D array, (2,)
# array( [1.,0.] )
Y = X.reshape(1,2)
# 2D array, (1,2)
# array( [[1.,0.]] )
Z = X.reshape(2,1)
# 2D array, (2,1)
# array( [[1.],
[0.]] )
A + 1
# (2,2) + scalar*I = (2,2)
# array( [[1.,2.],
# [3.,4.]] )
A + X
# (2,2) + (2,) = (2,2)
# array( [[1.,1.],
# [3.,3.]])
A + Y
# (2,2) + (1,2) = (2,2)
# array( [[1.,1.],
# [3.,3.]])
A + Z
# (2,2) + (2,1) = (2,2)
# array( [[1.,2.],
# [2.,3.]])
행렬 연산 함수 호출시 주의사항
import numpy as np
A = np.arange(4.).reshape(2,2)
# 2D array, (2,2)
# array( [[0.,1.],
# [2.,3.]] )
X = np.array( [1.,0.] )
# 1D array, (2,)
Y = X.reshape(1,2)
# 2D array, (1,2)
Z = X.reshape(2,1)
# 2D array, (2,1)
np.matmul(A,Y)
# (2,2)*(1,2) = Dimension Error
np.matmul(A,Z)
# (2,2)*(2,1) = (2,1)
# array( [[0.],
# [2.]] )
np.matmul(A,X)
# (2,2)*(2,) = (2,)
# array( [0.,2.] )
▪ 깊은 복사(deep copy)
서로 값만 같을 뿐 본질적으로 서로 다르기 때문에 한 변수가 수정될 시 다른 변수가 수정되지 않는다.
▪ 얕은 복사(shallow copy)
서로 다른 변수명이지만 본질적으로 서로 같은 대상을 의미하므로 하나의 변수 역시 수정이 된다.
import numpy as np
A = [1,2,3] # [1, 2, 3]
X = np.array(A) # array( [1, 2, 3] )
Z = X.copy() # deep copy
Z is X # False
Y = X # shallow copy
Y[0] = 10 #
X # array( [10, 2, 3] )
Y # array( [10, 2, 3] )
Y is X # True
X is Y # True
부분행렬은 얕은 복사이다.
import numpy as np
X = np.array( [1,2,3] )
Y = X[0:2] # shallow copy
Y[0] = 10 #
Y # array( [10,2] )
X # array( [10,2,3] )