2024.01.28 - [프로그래밍/파이썬 공부하기] - Python 공부하기 - 7-1 (Numpy)
저번 편에 이어 계속 Numpy에 대해 배워보겠습니다.
Numpy 인덱싱 / 슬라이싱
넘파이의 인덱싱, 슬라이싱은 리스트와 거의 동일합니다.
1. 1차원 배열
import numpy as np
scores = np.array([88,72,93,94,89,78,99])
print(scores[2]) # 인덱싱
print(scores[-1]) # 인덱싱
print(scores[1:4]) # 슬라이싱
print(scores[3:]) # 슬라이싱
print(scores[4:-1]) # 슬라이싱
print(scores[:3]) # 슬라이싱
93
99
[72 93 94]
[94 89 78 99]
[89 78]
[88 72 93]
조건문을 활용해서도 슬라이싱할 수 있습니다. 조건문을 이용할 시 넘파이 배열의 모든 요소에 대해 반복문을 돌리듯이 조건을 확인합니다.
import numpy as np
scores = np.array([88,72,93,94,89,78,99])
print(scores > 80)
print(scores[scores > 80])
[ True False True True True False True]
[88 93 94 89 99]
2. 2차원 배열
2차원 배열의 인덱싱, 슬라이싱은 콤마를 이용합니다.
인덱싱은 콤마로 행 / 열을, 슬라이싱은 콤마로 행 범위 / 열 범위를 지정해줍니다.
2차원 배열에 접근도 콤마로 할 수 있습니다.
<인덱싱, 접근>
import numpy as np
nparr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
print(nparr[0, 2]) # 0행 2열
print(nparr[2, -1]) # 2행 -1열 (마지막 열)
print(nparr[3, 3]) # 3행 3열
nparr[0,0] = 100 # 0행 0열 요소 변경
nparr[2, 2] = 1.25 # 2행 2열 요소 변경
print(nparr)
3
12
16
[[100 2 3 4]
[ 5 6 7 8]
[ 9 10 1 12]
[ 13 14 15 16]] # (0, 0), (2, 2) 요소 바뀜
2행 2열 요소를 1.25라는 소수로 바꿨지만 정수 넘파이 배열이기에 정수로 변환되어 들어간 것을 볼 수 있습니다.
<슬라이싱>
import numpy as np
nparr = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(nparr > 5)
print(nparr[nparr > 5])
print(nparr[:, 2]) # 행은 다, 열은 2열만
print(nparr[nparr[:, 2] > 5]) # 2열만 있는 배열 중 5보다 큰 애의 index만
print(nparr[:] % 2 == 0) # [:]은 그냥 모든 배열 -> 짝수인 애만
print(nparr[nparr % 2 == 0]) # 위 배열
print(nparr[nparr[:, 1] % 2 == 0]) # nparr[:, 1] % 2 == 0인 애들의 index가 nparr의 index로 들어감 -> 0, 2
print(nparr[0:2,1:3]) # 0~1행, 1~2열
print(nparr[0:2][1:3]) # 0~1행 잘라낸 거에서 1~2행 또 자름 -> 1행만 남음
[[False False False]
[False False True]
[ True True True]]
[6 7 8 9]
[3 6 9]
[[4 5 6]
[7 8 9]]
[[False True False]
[ True False True]
[False True False]]
[2 4 6 8]
[[1 2 3]
[7 8 9]]
[[2 3]
[5 6]]
[[4 5 6]]
Numpy 배열 다루기
다음은 Numpy 배열 관련한 함수들입니다.
1. arrange()
arrange()는 넘파이 배열을 생성하는 함수입니다. range()와 기능은 같지만 range()는 리스트를 반환하고, numpy()는 넘파이 배열을 반환한다는 차이가 있습니다.
numpy.arange(start, stop, step)
start : 데이터 생성을 시작할 값, 생략 시 0으로 처리
stop : 데이터 생성을 멈추는 값으로 생략 불가, stop-1까지 생성
step : 데이터 생성 간격, 생략 시 1로 처리
import numpy as np
print(list(range(5)))
print(np.array(range(5)))
print(np.arange(5))
print(np.arange(1,6))
print(np.arange(1,10,2))
[0, 1, 2, 3, 4]
[0 1 2 3 4]
[0 1 2 3 4]
[1 2 3 4 5]
[1 3 5 7 9]
2. linspace() / logspace()
linspace()는 선형적으로(linear) 넘파이 배열 값들을 생성해줍니다.
numpy.linspace(start, stop, num=50)
start : 데이터 생성을 시작할 값, 생략할 수 없음
stop : 데이터 생성을 멈추는 값으로 생략 불가, stop까지 생성
num : 데이터 생성 개수, 기본 값은 50개
logspace()는 지수적으로(logarithmic) 넘파이 배열 값들을 생성해줍니다.
numpy.logspace(start, stop, step)
start : 데이터 생성을 10^start부터 시작한다.
stop : 데이터 생성을 10^stop까지 한다.
step : 데이터 생성 개수, 기본 값은 50개
import numpy as np
print(np.linspace(1, 100))
print(np.logspace(0, 5, 10))
[ 1. 3.02040816 5.04081633 7.06122449 9.08163265
11.10204082 13.12244898 15.14285714 17.16326531 19.18367347
21.20408163 23.2244898 25.24489796 27.26530612 29.28571429
31.30612245 33.32653061 35.34693878 37.36734694 39.3877551
41.40816327 43.42857143 45.44897959 47.46938776 49.48979592
51.51020408 53.53061224 55.55102041 57.57142857 59.59183673
61.6122449 63.63265306 65.65306122 67.67346939 69.69387755
71.71428571 73.73469388 75.75510204 77.7755102 79.79591837
81.81632653 83.83673469 85.85714286 87.87755102 89.89795918
91.91836735 93.93877551 95.95918367 97.97959184 100. ]
[1.00000000e+00 3.59381366e+00 1.29154967e+01 4.64158883e+01
1.66810054e+02 5.99484250e+02 2.15443469e+03 7.74263683e+03
2.78255940e+04 1.00000000e+05]
3. reshape() / flatten()
reshape()는 넘파이 배열을 재배열해주고, flatten()은 1차원 배열로 만들어줍니다.
new_array = old_array.reshape( shape )
# shape = 변경하고 싶은 형태 (1차원 = (n, ), 2차원 = (n, m), 3차원 = (n, m, l) ...)
new_array = old_array.flatten()
※ reshape는 이전 배열의 원소 개수와 새롭게 얻고 싶은 형태의 원소 개수가 같아야 형태 변경이 가능
이전 형태 (n, m), 새로운 형태(l, k)인 경우 n*m = l*k를 만족해야 함.
import numpy as np
arr=np.arange(12)
print(arr)
print(arr.reshape(3,4))
print(arr.reshape(6,-1)) # -1 = 앞의 수 보고 알아서 맞춰줌
print(arr.flatten())
[ 0 1 2 3 4 5 6 7 8 9 10 11]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 0 1]
[ 2 3]
[ 4 5]
[ 6 7]
[ 8 9]
[10 11]]
[ 0 1 2 3 4 5 6 7 8 9 10 11]
난수
규칙성이 전혀 없는 난수의 열은 컴퓨터로 생성하는 것이 불가능합니다.
따라서 임의의 초기 값(seed)을 바탕으로 해시함수를 통해 난수 생성하는데, 컴퓨터가 규칙을 가지고 생성한 수로 이를 의사난수(pseudo random number)라 합니다.
np.random.rand(n) : 0부터 1까지 실수 n개 생성
np.random.randint(n) : 0부터 1까지 정수 n개 생성
import numpy as np
np.random.seed(100)
a=10
b=20
print(np.random.rand(5))
print(np.random.rand(5))
print((b-a)*np.random.rand(5)+a)
print(np.random.randint(1, 10, size=5))
print(np.random.randint(1, 10, size=(2,3)))
[0.54340494 0.27836939 0.42451759 0.84477613 0.00471886]
[0.12156912 0.67074908 0.82585276 0.13670659 0.57509333]
[18.91321954 12.09202122 11.8532822 11.0837689 12.19697493]
[5 2 6 4 5]
[[5 4 8]
[2 2 8]]
결국에는 넘파이의 난수도 seed를 바탕으로 한 것이기 때문에 seed만 같다면 다 같은 결과가 나오게 됩니다.
특정 범위의 난수 생성(a~b 사이 난수) : (b-a) * np.random.rand(개수) + a
정규분포난수
넘파이에서 사용하는 정규분포난수 함수는 randn()를 사용합니다. 이 함수는 평균은 0이고 표준 편차가 1이 되는 표준 정규 분포가 되도록 생성합니다.
import numpy as np
np.random.seed(100)
mu = 10 # 평균
sigma = 2 # 표준편차
print(np.random.randn(5)) # 평균 = 0, 표준편차 = 1
print(np.random.randn(2,3)) # 평균 = 0, 표준편차 = 1
randoms = mu + sigma * np.random.randn(5)
print(randoms) # 평균 = 10, 표준편차 = 2
[-1.74976547 0.3426804 1.1530358 -0.25243604 0.98132079]
[[ 0.51421884 0.22117967 -1.07004333]
[-0.18949583 0.25500144 -0.45802699]]
[10.87032698 8.8328099 11.63369414 11.34544161 9.79117771]
평균, 중앙값
np.mean() : 넘파이 배열의 평균을 계산하는 함수
np.median() : 넘파이 배열의 중앙값을 계산하는 함수 (요소 개수가 짝수인 경우는 중간에 있는 두 값의 평균 값을 출력
예) [1 2 3 4 5 6]의 중앙값은 3.5)
import numpy as np
np.random.seed(100)
mu = 5
sigma = 3
randoms = mu + sigma * np.random.randn(5)
print(randoms)
print(np.mean(randoms))
print(np.median(randoms))
print('')
randoms = mu + sigma * np.random.randn(100000)
print(np.mean(randoms))
print(np.median(randoms))
[-0.24929642 6.02804121 8.45910741 4.24269189 7.94396236]
5.284901289959775
6.028041209982506
5.008346837283384
5.007405105223565
당연하게도 개수가 늘수록 평균과 표준편차가 설정한 값에 가까워지겠죠.
np.zeros() / 올림&내림&반올림
np.zeros() : 0으로 채운 넘파이 배열 생성 (실수 형태로)
np.ceil() : 넘파이 배열에서 소수점 올림
np.floor() : 넘파이 배열에서 소수점 버림
np.round() : 넘파이 배열에서 주어진 소수점 자리까지 반올림
import numpy as np
np.random.seed(100)
z= np.zeros((2,3))
print(z)
n= np.random.rand(3)
print(n)
print(np.ceil(n))
print(np.floor(n))
print(np.round(n,2))
[[0. 0. 0.]
[0. 0. 0.]]
[0.54340494 0.27836939 0.42451759]
[1. 1. 1.]
[0. 0. 0.]
[0.54 0.28 0.42]
상관 계수
상관계수 : 두 변수 간에 어떤 선형적 관계를 가지고 있는지 분석하여 표현한 계수
corrcoef(x,y) 함수는 요소들의 상관 관계를 계산하여 상관 계수를 행렬로 표현합니다.
(자신과의 상관계수는 항상 1이고, 상관 계수 행렬은 대칭 행렬입니다)
import numpy as np
x = [i for i in range(100)]
y = [i ** 2 for i in range(100)]
z = [100 * np.sin(3.13*i / 100) for i in range(100)]
result = np.corrcoef(x, y)
print(result)
result = np.corrcoef([x, y, z])
print(result)
[[1. 0.96764439]
[0.96764439 1. ]]
[[ 1. 0.96764439 0.04908626]
[ 0.96764439 1. -0.20412168]
[ 0.04908626 -0.20412168 1. ]]
'프로그래밍 > 파이썬 공부하기' 카테고리의 다른 글
Python 공부하기 - 7-1 (Numpy) (6) | 2024.06.30 |
---|---|
Python 공부하기 - 6 (세트) (0) | 2024.06.30 |
Python 공부하기 - 5 (딕셔너리, 튜플) (1) | 2024.01.27 |
Python 공부하기 - 4 (리스트) (0) | 2024.01.26 |
Python 공부 - 3 (클래스, 메서드, 인스턴스, 객체, 속성) (0) | 2024.01.24 |