2-1 넘파일 배열 연산
NumPy 배열 연산은 요소 단위로 수행된다.
배열과 배열, 배열과 스칼라 값의 연산이 되고 브로드캐스팅 통해 서로 다른 크기의 배열도 자동 확장 연산한다.
# 배열 간 연산(1차원)
a1 = np.array([1,2,3])
a2 = np.array([4,5,6])
print(a1 + a2)
print(a1 - a2)
[5 7 9]
[-3 -3 -3]
# 배열 간 연산 (2차원)
a1 = np.arange(1,5).reshape(2,2)
a2 = np.arange(11,15).reshape(2,2)
print(a1)
print(a2)
print(a1 + a2)
print(a1 - a2)
3, 4번째가 a1+ a2 / a1- a2 값
+,-,*,/ 와 같은 산술 연산자를 바로 사용할 수 있다.
# 배열과 스칼라 연산(1차원)
a1 = np.array([1,2,3,4])
print(a1 + 10)
print(a1 * 2)
[11 12 13 14]
[2 4 6 8]
# 배열과 스칼라 연산 (2차원)
a1 = np.arange(1,5).reshape(2,2)
a2 = np.arange(11,15).reshape(2,2)
print(a1)
print(a2)
print(a1 + 5)
print(a2 * 3)
print(a2 / 2)
배열과 단일 값(스칼라)의 연산 시 요소별로 단일 값 연산을 한다.
이는 스칼라가 모든 원소에 적용하는 것이라서, a2 원소에서 3씩 곱해져 3번째 결과값이 나오는 거다.
# 배열의 구조가 다를 경우
a1 = np.array([1,2])
a2 = np.array([1,2,3])
#print(a1 + a2) #ValueError
브로드캐스팅 설명
전개 예시
a1 = np.array([[1,2,3],
[4,5,6]]) # (2,3) 배열
a2 = np.array([10,20,30]) #길이가 3인 1차원 배열 (3,)
# 1차원 길이 3
[10,20,30]
# 2차원으로 변형 (1,3)
[[10,20,30]]
#2차원 행이 2 -> 2로 확장
[[10,20,30],
[10,20,30]]
print(a1 + a2)
의 결과물
[[11 22 33]
[14 25 36]]
#브로드캐스팅 예제
a1 = np.array([[1],[2],[3]]) #(3,1)
a2 = np.array([10,20,30]) #(3,)
#a2 = (3,) > (1,3)변형 : 한줄 자리를 3줄로 바꿔야 하니까
[[10,20,30]]
#a1 과 a2 비교 > (3,1), (1,3)
[[1,1,1],[2,2,2],[3,3,3]]
[[10,20,30],[10,20,30],[10,20,30]]
print(a1+a2)
[[11 21 31]
[12 22 32]
[13 23 33]]
이하 배열 관련 실습
더보기
#실습
#다음 배열을 생성하고, 모든 요소에 3을 더하세요
arr = np.array([1, 2, 3, 4])
print(arr + 3)
#아래 2차원 배열에서 각요소를 -1로 곱한 새로운 배열을 만드세요
arr = np.array([[5, 10],
[15, 20]])
arr_1 = arr * -1
print(arr_1)
#아래 두 배열의 요소별 곱셈과 나눗셈 결과를 각각 출력하세요
arr1 = np.array([2, 4, 6])
arr2 = np.array([1, 2, 3])
print(arr1 / arr2)
print(arr1 * arr2)
[4 5 6 7]
[[ -5 -10]
[-15 -20]]
[2. 2. 2.]
[ 2 8 18]
# 모든 요소 최대값을 100만들기 위해 필요한 값을 더한 결과 배열을 브로드캐스팅
arr = np.array([[95,97],[80,85]])
a1 = 100 - arr
print(a1)
print(arr + a1)
#2차원 배열에서 각 행에 다른 값을 곱하여 새로운 배열 완성(브로드캐스팅)
arr5 = np.array([[1,2,3],[4,5,6]])
# 첫 번째 행 10 곱, 두번째 행 100 곱
a2 = np.array([[10],[100]])
print(arr5 * a2)
[[ 5 3]
[20 15]]
[[100 100]
[100 100]]
[[ 10 20 30]
[400 500 600]]
#아래 배열에서 각 행마다 다른 스칼라 값 더하기
#1차원 배열 만들어 계산 1행 100, 2행 200, 3행 300 더하기
arr6 = np.array([[10,20],
[30,40],
[50,60]])
a3 = np.array([100,200,300]).reshape(3,1)
print(arr6 + a3)
[[110 120]
[230 240]
[350 360]]
2-2 통계 함수 및 집계 연산
np.argmin (): 배열에서 최소값이 있는 인덱스 반환
np.argmax (): 배열에서 최대값이 있는 인덱스 반환.
더보기
a = np.array([[1,2,3],[4,5,6]])
print("원소의 합:", np.sum(a))
print("원소의 평균:",np.mean(a))
print("표준편차:",np.std(a))
print("최대값:",np.max(a))
print("최소값:",np.min(a))
print("최대값의 인덱스:",np.argmax(a))
print("최소값의 인덱스:",np.argmin(a))
원소의 합: 21
원소의 평균: 3.5
표준편차: 1.707825127659933
최대값: 6
최소값: 1
최대값의 인덱스: 5
최소값의 인덱스: 0
축(axis) 단위 연산
axis = 0 -> 가장 높은 차원 기준 - >행 기준
행 기준 = 행을 따라 연산 = 행을 증가시키며 연산 : 열(column) 단위로 계산 (세로)
axis = 1 -> 그 다음 차원 기준 - >열 기준
열 기준 = 열을 따라 연산 = 열을 증가시키며 연산 : 행(row) 단위로 계산 (가로)
axis = n -> n번째 차원을 기준으로 연산.
a = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
print("행기준 합", np.sum(a, axis = 0))
print("열기준 합", np.sum(a, axis = 1))
print("행기준 평균", np.mean(a, axis = 0))
print("열기준 평균", np.mean(a, axis = 1))
# 누적 연산
arr = np.array([1,2,3,4])
print(np.cumsum(arr))
print(np.cumprod(arr))
[ 1 3 6 10]
[ 1 2 6 24]
np.cumsum() 누적 합
np.cumprod() 누적 곱
이하 실습 예제들
더보기
#아래 배열의 전체 합계와 평균을 각각 구하세요
arr= np.array([5, 10, 15, 20])
print("합", np.sum(arr))
print("평균", np.mean(arr))
#다음 2차원 배열에서 전체 최소값과 최대값을 구하세요
arr1= np.array([[3, 7, 1],
[9, 2, 8]])
print("최소값:",np.min(arr1))
print("최대값:",np.max(arr1))
#아래 배열에서 각 열의 합계와 각 행의 합계를 각각 구하세요
arr2= np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print("행기준 합", np.sum(arr2, axis = 0)) #세로방향
print("열기준 합", np.sum(arr2, axis = 1)) #가로방향
#아래 배열에서 행별 평균과 열별 평균을 각각 구하세요
arr3= np.array([[10, 20],
[30, 40],
[50, 60]])
print("행기준 평균", np.mean(arr3, axis = 0))
print("열기준 평균", np.mean(arr3, axis = 1))
#1차원 배열에서 전체 표준편차를 구하고, 각 요소가 평균으로부터
# 얼마나 떨어져 있는지 편차 배열을 만드세요. (값 -평균)
arr4= np.array([2, 4, 4, 4, 5, 5, 7, 9])
print("표준편차:",np.std(arr4))
print("평균:",np.mean(arr4))
print("오차:", arr4 - np.mean(arr4))
#아래 2차원 배열에서 행 단위 누적 합과 열 단위 누적 곱을 각각 구하세요
arr5= np.array([[1, 2, 3],
[4, 5, 6]])
print("행기준 누적 합", np.cumsum(arr5, axis = 0))
print("열기준 누적 곱", np.cumprod(arr5, axis = 1))
2-3 논리 연산과 조건 연산
데이터 분석에서도 NumPy 논리 연산자를 쓰기 때문에 헷갈리지 않도록 한다. (EDA파트에서 다시 보고 있다.
np.where()
조건 기반 선택 함수, Python의 삼항 연산자와 유사한 역할을 한다.
arr = np.array([10,20,30,40,50])
result = np.where(arr > 30, "hing","low")
result 의 결과
array(['low', 'low', 'low', 'hing', 'hing'], dtype='<U4')
arr = np.array([10,20,30,40,50])
조건만 넣을 경우 조건을 만족하는 원소의 인덱스를 반환
result = np.where(arr > 30)
print(result)
print(arr[result])
(array([3, 4]),)
[40 50]
# and 연산(&)
arr = np.array([10,20,30,40,50])
mask = (arr > 10) & (arr < 50)
print(mask)
T/F만 알려줌 [False True True True False]
print("&연산", arr[mask])
요소 알려줌 &연산 [20 30 40]
# or 연산(|) #shift + \
mask_or = (arr > 40) | (arr < 20)
print(mask_or)
[ True False False False True]
print("|연산",arr[mask_or])
|연산 [10 50]
#not연산(~)
mask_not = ~(arr>30)
print(arr[mask_not]) [10 20 30]
관련 실습 예제들
더보기
#실습
#1차원 배열 [5, 12, 18, 7, 30, 25]에서 10보다 크고 20보다 작은 값만 필터링
a1 = np.array([5, 12, 18, 7, 30, 25])
a1_p = (a1 > 10) & (a1 < 20)
print(a1[a1_p])
#배열 [10, 15, 20, 25, 30, 35]에서 15 이하이거나 30 이상인 값만 선택
a2 = np.array([10, 15, 20, 25, 30, 35])
a2_p = (a2 <= 15) | (a2 >= 30)
print(a2[a2_p])
#배열 [3, 8, 15, 6, 2, 20]에서 10 이상인 값을 모두 0으로 변경
a3 = np.array([3, 8, 15, 6, 2, 20])
a3_p = (a3 >= 10)
a3_n = np.where(a3_p, 0 ,a3)
print(a3_n)
#a3[a3 >=10] = 0
#배열 [7, 14, 21, 28, 35]에서 20 이상인 값은 "High", 나머지는 "Low"로 표시하는 새로운 배열을 생성
a4 = np.array([7, 14, 21, 28, 35])
a4_p = np.where(a4 >= 20, "hing","low")
print(a4_p)
종합 예제
더보기
#0~9 범위 배열에서 짝수 그대로 두고 홀수만 x10곱 변환하기.
a5 = np.array([0,1,2,3,4,5,6,7,8,9])
a5_p = np.where(a5 % 2 == 0 , a5, a5 *10)
print(a5_p)
#아래 2차원 배열에서 20 이상, 40이하만 값 선택
a6 = np.array([[10,25,30],
[40,5,15],
[20,35,50]])
a6_p = (a6 >= 20 ) & (a6 <= 40)
print(a6[a6_p])
# 배열 [1,2,3,4,5,6]에서 3배수 아닌 것만 선택
a7= np.array([1,2,3,4,5,6])
a7_p = (a7 % 3 != 0)
print(a7[a7_p])
# 랜덤 정수 (0~100) 10개 배열에서 새 배열 만들기
#50 이상 값은 그대로, 50 미만은 50으로 변경
a8 = np.random.randint(0,101,size=10)
print(a8)
print(np.where(a8 >=50, a8, 50))
#2차원 배열에서 아래와 같이 분류된 문자열 생성
a9 = np.array([[5,50,95],
[20,75,10],
[60,30,85]])
a9_p = np.where(a9 >= 70, "A",
np.where(a9 >= 30, "B","C"))
print(a9_p)
2-4 행렬 곱셈
- 두 행렬을 곱해서 새로운 행렬을 생성하는 연산
- 첫 번째 행렬의 열수(세로)와 두번째 행렬의 행수(가로)가 같아야 곱셈이 가능함
- np.dot(),np.matmul() > 사용
예시
1차원 배열 간 연산 -> 내적
a = np.array([1,2,3])
b = np.array([4,5,6])
print(np.dot(a,b)) # 1*4 + 2*5 + 3*6
결과값: 32
같은 위치의 숫자를 곱하고 모두 더함(내적)
결과= 숫자(스칼라)
물건 구매
데이터 분석에서 벡터랑 배열
c = [1000,2000,5000,10000]
d = [10, 3, 5, 7]
print(np.dot(c,d))
결과 값: 111000
2차원 배열간 연산 -> 행렬 곱셈
a = np.array([[1,2,3],[4,5,6]]) #(2,3)
b = np.array([[1,2],[3,4],[5,6]]) #(3,2)
print(np.dot(a,b))
표준적인 행렬 곱셉
넘파일의 행렬곱셈
np.matmul(a,b)
Matrix Multiplication
스칼라 연산 시도시 에러
0차원은 불가함.
a = np.array(3)
b = np.array(4)
print(np.matmul(a,b)) #ValueError
# 1차원 배열간 연산 - 내적 연산
a = np.array([1,2])
b = np.array([3,4])
print(np.matmul(a,b)) # 1*3 + 2*4 <교차한 지점에만
dot과 같은 내적 연산이다.
# 2차원 배열간 연산 > 행렬 곱셈
a = np.array([[1,2,3],
[4,5,6]]) #(2,3)
b = np.array([[1,2],
[3,4],
[5,6]]) #(3,2)
print(np.matmul(a,b))
# 1*1+2*3+3*5(22) / 1*2 + 2*4 + 3*6(28)
# 4
[[22 28]
[49 64]]
#2차원 * 1차원 간 연산
c = np.array([[1,2],[3,4]]) #(2,2)
d = np.array([5,6]) #(2,)
print(np.matmul(c,d)) #열과 행의 개수가 맞아야 계산 됨.
print(np.matmul(d,c)) # 바뀌면 값 달라짐. 순서 유의
[17 39]
[23 34]
#NumPy 행렬 곱셈 - @ (python 3.5 버전 이상)
e = np.array([[1,2,3]])
f = np.array([[1,2],
[3,4],
[5,6]])
print(np.matmul(e,f))
print(e @ f)
동일하게 [[22 28]] 출력
관련 실습
더보기
#실습
#1부터 9까지의 정수로 채워진 (3, 3) 배열 A와, 모두 2로 채워진 (3, 2) 배열 B를 만들고 곱하세요
c1 = np.arange(1,10).reshape(3,3)
c2 = np.full((3,2), 2)
print(np.matmul(c1,c2)) # c1 @ c2 해도 됨.
#4×4 단위행렬 I와, 4×4 난수 행렬 M(0~9 사이 정수) 간의 곱을 구하고, 결과와 M이 동일한지 확인하세요
i = np.eye(4, 4) #단위행렬 생성식 eye
m = np.random.randint(1,10,(4,4))
print("i와 m 값\n", np.matmul(i,m))
print(m)
#모든 값이 1인 (2, 5) 배열 X와, 5부터 14까지의 연속된 정수로 채워진 (5, 2) 배열 Y를 만들어 곱하세요
x = np.full((2,5),1)
y = np.arange(5,15).reshape(5,2)
print("x와 y 곱\n", np.matmul(x,y))
#0 이상 5 미만의 임의의 정수로 채워진 (3, 2) 배열 C와 (2, 3) 배열 D를 각각 만들어
# 곱한 결과의 shape와 값을 출력하세요
c = np.random.randint(0,5,(3,2))
d = np.random.randint(0,5,(2,3))
print(np.matmul(c,d).shape)
print(c @ d)