■ 기본 연산
- 배열에 대한 산술연산자는 각각의 요소별로 적용된다.
- 연산 시 자료형은 적절하게 형변환(upcasting) 된다.
a = np.ones(3, dtype=np.int32)
print(a.dtype.name)
b = np.linspace(0, np.pi, 3)
print(b.dtype.name)
# 서로 상응하는 원소끼리 더하기 연산이 이루어짐
c = a + b
print(c)
int32
float64
[1. 2.57079633 4.14159265]
■ 통계 연산
- 통계 연산은 axis와 밀접한 관계가 있다.
- 축 값을 입력하지 않으면 모든 원소에 대한 연산 결과를 출력한다.
a = np.arange(12).reshape(3, 4)
print(a)
print('-'*30)
# 축 값을 지정하지 않으면 모든 원소에 대한 합을 구함
print(a.sum())
print('-'*30)
# 각 열의 합
print(a.sum(axis=0))
print('-'*30)
# 각 행의 평균
print(a.mean(axis=1))
print('-'*30)
# 각 행의 누적 합
print(a.cumsum(axis=1))
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
------------------------------
66
------------------------------
[12 15 18 21]
------------------------------
[1.5 5.5 9.5]
------------------------------
[[ 0 1 3 6]
[ 4 9 15 22]
[ 8 17 27 38]]
○ np.average()
- 주어진 축에 따라 가중평균을 계산한다.
- avg = sum(a * weights) / sum(weights)
a = np.arange(6).reshape(3, 2)
print(a)
# 각 행별로 가중평균을 구함
# 0.75 = 0*(1/4) + 1*(3/4) / (1/4 + 3/4)
print(np.average(a, axis=1, weights=[1/4, 3/4]))
[[0 1]
[2 3]
[4 5]]
[0.75 2.75 4.75]
○ np.amin() / np.amax()
- axis을 따른 배열의 최소 또는 최대 값
a = np.arange(1, 10).reshape(3, 3)
print(a)
print('-'*30)
# 각 열별로 최소 값
print(np.amin(a, axis=0))
print('-'*30)
# 각 열별로 최대 값
print(np.amax(a, axis=0))
print('-'*30)
# 축 옵션을 주지 않으면 전체 요소 중에서 찾음
print(np.amin(a))
[[1 2 3]
[4 5 6]
[7 8 9]]
------------------------------
[1 2 3]
------------------------------
[7 8 9]
------------------------------
1
○ np.median()
- axis을 따른 배열의 중앙값
○ np.var(), np.std()
- axis을 따른 배열의 분산과 표준편차
▶ 최소값, 최대값 argument 위치
- np.argmax() : 제일 큰 값의 위치 정보를 반환
- np.argmin() : 제일 작은 값의 위치 정보를 반환
- np.where(조건) : 조건에 맞는 값의 위치 정보를 반환
- np.where(조건, 조건에 맞을 때 값, 조건과 다를 때 값)
a = np.array([5,6,2,52,90,1,6])
print(np.argmax(a)) # 0부터 시작했을 때 4번 째 위치 (90)
print(np.argmin(a)) # 0부터 시작했을 때 5번 째 위치 (1)
# a 배열에서 5를 초과하는 위치
print(np.where(a > 5))
# 5를 초과하는 값은 1로, 그렇지 않은 값은 -1로 변경
print(np.where(a > 5, 1, -1))
# 5를 초과하는 값은 원래 값 그대로, 그렇지 않은 값은 0으로 변경
print(np.where(a > 5, a, 0))
(array([1, 3, 4, 6], dtype=int64),)
[-1 1 -1 1 1 -1 1]
[ 0 6 0 52 90 0 6]
■ 비교 연산
- 연산자를 이용하여 요소별(element-wise) 비교
- ==, !=, >, >=, <, <=
import numpy as np
a = np.array([1, 2, 3])
b = np.array([1, 2, 3])
c = np.array([3, 2, 5])
print(a == b) # [True True True]
print('-'*20)
print(a == c) # [False True False]
a = np.arange(1, 10).reshape(3, 3)
print(a)
print('-'*20)
# a 다차원 배열에 대해서 각 요소별 비교
result = a % 2 == 0
print(result)
# 짝수에 해당하는 요소의 개수
print(np.sum(result)) # 4개
[[1 2 3]
[4 5 6]
[7 8 9]]
--------------------
[[False True False]
[ True False True]
[False True False]]
4
○ np.all(), np.any()를 이용한 비교
- all() : 요소 전체가 같아야 하나의 True 값을 반환
- any() : 요소 중 어느 하나만 같아도 True 값을 반환
a = np.array([1, 2, 3])
b = np.array([1, 2, 3])
c = np.array([3, 2, 5])
print(np.all(a == b)) # True
print(np.all(a == c)) # False
print('-'*20)
print(np.any(a == b)) # True
print(np.any(a == c)) # True
■ 논리 연산
- np.logical_and(), np.logical_or(), np.logical_not(), np.logical_xor()
x = np.arange(1, 11).reshape(2, 5)
print('x 행렬:')
print(x)
print('-'*20)
y = x % 2 == 0
print('y 행렬: 짝수면 True, 홀수면 False')
print(y)
print('-'*20)
z = x >= 4
print('z 행렬: 4 이상이면 True, 미만이면 False')
print(z)
print('-'*20)
print('y and z 행렬')
print(np.logical_and(y, z))
print('-'*20)
# 짝수이면서 4 이상인 요소의 개수 (True의 값 개수)
print('y and z 행렬의 총합')
print(np.sum(np.logical_and(y, z))) # 4개
print('-'*20)
# boolean indexing (True에 해당하는 요소의 값만 보여줌)
print(x[np.logical_and(y, z)]) # [ 4 6 8 10]
x 행렬:
[[ 1 2 3 4 5]
[ 6 7 8 9 10]]
--------------------
y 행렬: 짝수면 True, 홀수면 False
[[False True False True False]
[ True False True False True]]
--------------------
z 행렬: 4 이상이면 True, 미만이면 False
[[False False False True True]
[ True True True True True]]
--------------------
y and z 행렬
[[False False False True False]
[ True False True False True]]
--------------------
y and z 행렬의 총합
4
--------------------
[ 4 6 8 10]
■ 정렬
import numpy as np
np.random.seed(10)
data = np.random.randint(1, 50, 10)
# np.random.randint : end값 포함하지 않음, 모양을 지정할 수 있음
print(data)
[10 37 16 1 29 26 30 49 30 9]
- np.sort() : 데이터를 오름차순으로 정렬한다.
- 내림차순으로 정렬하는 별도의 옵션은 없다.
print(np.sort(data))
# 슬라이싱을 통해 내림차순 정렬이 가능하다
print(np.sort(data)[::-1])
[ 1 9 10 16 26 29 30 30 37 49]
[49 37 30 30 29 26 16 10 9 1]
- np.argsort() : 오름차순으로 정렬한 데이터의 정렬 전 인덱스 값을 반환한다.
# [10 37 16 1 29 26 30 49 30 9] -> [ 1 9 10 16 26 29 30 30 37 49]
# 정렬 후 원본 데이터의 인덱스 값을 반환
print(np.argsort(data))
[3 9 0 2 5 4 6 8 1 7]
# argsort()를 이용한 정렬
# 팬시 인덱싱
# 원본 데이터에 인덱스 값을 넣어줌
idx = np.argsort(data)
print(data[idx])
[ 1 9 10 16 26 29 30 30 37 49]
[문제] 학생 이름과 점수 데이터를 이용하여 성적이 우수한 학생 순서로 이름을 출력하세요.
name = ['홍길동', '저팔계', '사오정', '전우치', '삼장법사']
score = [75, 100, 95, 56, 99]
# 다차원 배열로 변환
name = np.array(name)
score = np.array(score)
# 오름차순으로 정렬 후 원본 데이터의 위치 값을 가져옴
sorted_idx = np.argsort(score)
# 인덱싱 값으로 넣은 후 슬라이싱하여 내림차순으로 반환
print(name[sorted_idx][::-1])
['저팔계' '삼장법사' '사오정' '홍길동' '전우치']
■ 행렬 연산
▶ * 연산자
- 형태가 동일한 두 행렬을 원소끼리(element-wise) 곱하는 연산자
- shape이 다르면 오류 발생
- 교환법칙 성립 : A * B == B * A
a = np.array([[1, 1],
[0, 1]])
b = np.array([[2, 0],
[3, 4]])
# 교환법칙 성립
print(a * b)
print(b * a)
a = np.arange(6).reshape(2, 3)
b = np.arange(6).reshape(3, 2)
# print(a * b) # shape이 달라서 오류 발생
[[2 0]
[0 4]]
[[2 0]
[0 4]]
▶ np.dot()
- 두 벡터의 내적을 계산하는 함수
- 내적이란 벡터에서 서로 대응하는 성분끼리 곱한 다음 그것들을 모두 더한 것을 의미하며, 내적의 결과는 단일 값인 스칼라가 된다.
- a·b 또는 <a,b>로 표현 : a1*b1 + a2*b2 + ... + an*bn
- 행렬 곱에서도 사용이 가능하지만, 공식 문서에서는 np.matmul() 함수 사용을 권장
a = np.array([3,4,6,3,9])
b = np.array([6,8,1,3,9])
c = np.dot(a,b) # 또는 a.dot(b)
print(c) # 3*6 + 4*8 + ... + 9*9 = 146
- 두 행렬의 곱을 계산하려면 첫 번째 행렬의 열의 크기와 두 번째 행렬의 행의 크기가 같아야 한다.
a = np.array([[1, 1],
[0, 1]])
b = np.array([[2, 0],
[3, 4]])
# 행렬의 곱에서는 교환법칙이 성립 안됨
print(a.dot(b))
print('-'*20)
print(b.dot(a))
[[5 4]
[3 4]]
--------------------
[[2 2]
[3 7]]
▶ np.matmul() / @ 연산자
a = np.array([[1, 1],
[0, 1]])
b = np.array([[2, 0],
[3, 4]])
print(a@b)
print('-'*20)
a = np.array([[1, 0, 3], [0, 2, 4]]) # 2행3열
b = np.array([[4, 1],[2, 2], [2, 3]]) # 3행2열
print(np.matmul(a,b)) # 2x3 @ 3x2 -> 2x2
[[5 4]
[3 4]]
--------------------
[[10 10]
[12 16]]
▶ 전치(transpose)
- 전치는 기존 행렬의 행과 열을 교환하는 것
- 즉, 주대각선을 기준으로 반사 대칭하는 것을 말한다.
x = np.arange(1, 5).reshape(2, 2)
print(x)
print('-'*20)
print(x.T)
print('-'*20)
print(np.transpose(x))
[[1 2]
[3 4]]
--------------------
[[1 3]
[2 4]]
--------------------
[[1 3]
[2 4]]
'데이터 분석 > 넘파이' 카테고리의 다른 글
[Numpy 연습문제] (0) | 2023.11.08 |
---|---|
[Numpy] random 모듈 (0) | 2023.11.08 |
[Numpy] Broadcasting (0) | 2023.11.08 |
[Numpy] 인덱싱 / 슬라이싱 / 반복 (1) | 2023.11.08 |
[Numpy] 배열 생성 (1) | 2023.11.07 |