넘파이의 주요 특징은 n차원 배열 ndarray
객체가 있다. 이 자료형을 이용해서 연산을 빠르게 처리할 수 있다 !
import numpy as np
data = np.random.randn(2, 3)
data
output
array([[-1.25858421, 0.21625778, 1.48456228],
[-1.5184562 , 0.54263558, -0.62803821]])
여기서 수학 연산을 어케하냐?!
ㄴ
10 * data
다른 언어에선 이렇게 하면 int * list 는 안된다고 typeError가 뜰 텐데 (아마도?) numpy에서는 각 요소들에 10씩 아주 잘 곱해진다 ~~
배열의 크기를 구하고 싶다면 data.shape
을 쓰면 되고 출력은 (행,열) 이렇게 나온다 ! 그리고 원소들의 자료형을 알고 싶다면 data.dtype
을 쓰자 ~~
넘파이 배열을 만드는 방법
: numpy.array
메소드를 이용!
data1 = [1, 2, 3.5, 4, 5]
arr = np.array(data1)
arr
output
array([1. , 2. , 3.5, 4. , 5. ])
다차원 배열을 만드는 방법은 그냥 괄호안에 배열을 몇개 넣어주면 된당
data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
arr2 = np.array(data2)
arr2
output
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
만약 배열의 요소들이 전부 0이나 1이었으면 한다면 엄청 쉽게 배열을 만들 수 있는 방법이 있다 !!
0으로만 n개 채우는 방법
np.zeros(10)
output
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
1로만 nxm 차원 배열 만드는 방법
np.ones((2, 3))
output
array([[1., 1., 1.],
[1., 1., 1.]])
arange
함수 ~~는 range
함수와 대응되는 거지만 반환값은
넘파이배열
이다
np.arange(10)
output
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
형 변환 하는 법 ! -> astype
메소드 이용하기
arr = np.array([1, 2, 3, 4, 5])
arr.dtype
arr_float = arr.astype(np.float64)
arr_float.dtype
output
dtype('int32')
dtype('float64') # 바뀌었다 !
넘파이는 연산에 아주 뛰어난 라이브러리?여서 반복문을 쓰지 않고 연산을 할 수 있다 !!
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
arr
output
array([[1., 2., 3.],
[4., 5., 6.]])
ㄴ 배열 준비 !!
arr * arr
output
array([[ 1., 4., 9.],
[16., 25., 36.]])
두 배열 간 연산도 쉽다
arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
arr < arr2
output
array([[False, True, False],
[ True, False, True]])
arr = np.arange(10)
arr
arr[5:8]
output
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
array([5, 6, 7])
이렇게 배열 안에서 원하는 인덱스~인덱스의 요소만 뽑아올 수 있다 !
근데 넘파이 슬라이싱이 파이썬 리스트와 다른점 중 하나는 선택 부분의 값을 변경하면 원래 배열의 같은 위치의 값도 변경된다는 것이다 !
배열 일부분 복사하는 방법 = copy
메소드 쓰기
arr_copy = arr[5:8].copy()
arr_copy
output
array([500, 500, 500])
만약에 copy해서 값을 바꿔도
arr_copy[:] = -100
arr_copy
output
array([-100, -100, -100])
arr_copy값은 변경되지만 arr값은 변경이 안된다
arr
output
array([ 0, 1, 2, 3, 4, 500, 500, 500, 8, 9])
이 부분이 어렵다 !!
스터디 시간에 물어봐야지 개어렵ㄷ네
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
np.random.seed(0)
data = np.random.randn(7, 4)
data
output
array([[ 1.76405235, 0.40015721, 0.97873798, 2.2408932 ],
[ 1.86755799, -0.97727788, 0.95008842, -0.15135721],
[-0.10321885, 0.4105985 , 0.14404357, 1.45427351],
[ 0.76103773, 0.12167502, 0.44386323, 0.33367433],
[ 1.49407907, -0.20515826, 0.3130677 , -0.85409574],
[-2.55298982, 0.6536186 , 0.8644362 , -0.74216502],
[ 2.26975462, -1.45436567, 0.04575852, -0.18718385]])
ㄴ 이러한 배열 준비
bob
에 해당하는 행만 선택하기를 원한다면 비교연산자 ==
를 사용하자 !
names == 'Bob'
output
array([ True, False, False, True, False, False, False])
다중 인덱스를 사용해보자
data[names == 'Bob', 2:]
output
array([[0.97873798, 2.2408932 ],
[0.44386323, 0.33367433]])
ㄴ 내 생각엔 [names == 'Bob']
이게 나타내는게 0과 3번 임. 그래서 0,3 번 행 추출하고 2:
를 써서 2번째 요소부터 끝까지 출력해라 ~ 인 것 같다
부정연산자를 사용해도 된당
data[~(names == 'Bob')]
output
array([[ 1.86755799, -0.97727788, 0.95008842, -0.15135721],
[-0.10321885, 0.4105985 , 0.14404357, 1.45427351],
[ 1.49407907, -0.20515826, 0.3130677 , -0.85409574],
[-2.55298982, 0.6536186 , 0.8644362 , -0.74216502],
[ 2.26975462, -1.45436567, 0.04575852, -0.18718385]])
정수 배열을 이용해서 인덱싱을 자유롭게 할 수 있음 !!
일단 배열 만들기!
arr = np.empty((8, 4)) # 8x4 크기의 비어있는 다차원 배열 생성 코드
for i in range(8):
arr[i] = i
arr
output
array([[0., 0., 0., 0.],
[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.],
[4., 4., 4., 4.],
[5., 5., 5., 5.],
[6., 6., 6., 6.],
[7., 7., 7., 7.]])
원하는 행을 뽑아서 원하는 순서대로 배열하고 싶으면 인덱스를 배열로 만들어서 대입하면 된당
arr[[4, 3, 0, 6]]
output
array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
여러개의 정수 배열 인덱싱
# 0~31 까지의 연속된 정수를 포함하는 1차원 배열 생성하고 이 배열을 8x4의 2차원 배열 모양으로 변경하는 코드
arr = np.arange(32).reshape(8, 4)
arr
output
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31]])
정수열 배열 인덱스를 2개의 성분에 대입하면 결과값은 각각의 튜플에 해당하는 일차원 배열이 나옴
arr[[1, 5, 7, 2], [0, 3, 1, 2]]
output
array([ 4, 23, 29, 10])
ㄴ 1 5 7 2
가 행 인덱스, 0 3 1 2
가 열 인덱스이다 !
전치(transpose)는 크기 변경의 특별한 형태이다
배열은 .transpose
로 써도 되고 .T
로 써도 된당
배열 준비
arr = np.arange(15).reshape((3,5))
arr
output
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
전치 !!
arr.T
output
array([[ 0, 5, 10],
[ 1, 6, 11],
[ 2, 7, 12],
[ 3, 8, 13],
[ 4, 9, 14]])
두 행렬의 곱을 계산할 때엔 dot
메소드를 사용한다
arr.dot(arr.T)
output
array([[ 30, 80, 130],
[ 80, 255, 430],
[130, 430, 730]])
고차원 배열 넘 어렵다.. ㅠㅠ
고차원배열에서 전치는 축 인덱스를 인자로 가짐
ex) 2x3x4 3차원 배열
아 에러 왜지 !!!???!!
ㄴ 넘파이 배열의 성분끼리 연산을 할 수 있는 함수를 말한다 ex) sqrt
, exp
배열 준비
arr = np.arange(10)
arr
output
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
sqrt 함수 적용
np.sqrt(arr)
output
array([0. , 1. , 1.41421356, 1.73205081, 2. ,
2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ])
exp 함수 적용!
ㄴ exp 함수는 지수 함수를 계산하는 함수이당
np.exp(arr)
output
array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,
5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,
2.98095799e+03, 8.10308393e+03])
add 함수 (더하기)
np.add(arr, arr)
output
array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
maximum 함수 (최댓값 구하기)
np.maximum(x, y)
output
array([ 1.76405235, 1.45427351, 0.97873798, 2.2408932 , 1.86755799,
0.33367433, 1.49407907, -0.15135721, 0.3130677 , 0.4105985 ])
modf함수 (정수와 소수부분을 각각 반환)
(배열 준비)
rng = np.random.RandomState(0)
arr = rng.randn(7) * 5
arr
output
array([ 8.82026173, 2.00078604, 4.89368992, 11.204466 , 9.33778995,
-4.8863894 , 4.75044209])
rem_part, int_part = np.modf(arr)
rem_part #소수 부분
output
array([-0.93591925, 0.66389607, 0.34679385, 0.77473713, 0.8908126 ,
-0.43892874, -0.90398234])
ㄴ 원래 이렇게 나와야하는데 나는
array([ 8.20261730e-01, 7.86041836e-04, 8.93689921e-01, 2.04465996e-01,
3.37789951e-01, -8.86389399e-01, 7.50442088e-01])
왜 이렇게 나오는거지....... 스터디시간에 물어보자 !!
int_part # 정수 부분
output
array([ 8., 2., 4., 11., 9., -4., 4.])
ㄴ 또 정수 부분을 잘 나온다..
1차원 자료를 이용해서 2차원 계산을 쉽게 할 수 있다 !
meshgrid
함수를 사용하면 모든 격자점의 x,y 좌표를 계산할 수 있음
points = np.arange(-5, 5, 0.01)
-5~5 까지 1000개의 점을 격자형으로 만듦
xs, ys = np.meshgrid(points, points)
ys
output
array([[-5. , -5. , -5. , ..., -5. , -5. , -5. ],
[-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],
[-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],
...,
[ 4.97, 4.97, 4.97, ..., 4.97, 4.97, 4.97],
[ 4.98, 4.98, 4.98, ..., 4.98, 4.98, 4.98],
[ 4.99, 4.99, 4.99, ..., 4.99, 4.99, 4.99]])
ㄴ 구글 코랩에서는 module 'numpy' has no attribute 'meshigrid'
이렇게 뜨긴하는데.. 왜지 지원안해주나
함수 값 계산은 각 점에서의 스칼라 계산
z = np.sqrt(xs ** 2 + ys ** 2)
z
output
array([[7.07106781, 7.06400028, 7.05693985, ..., 7.04988652, 7.05693985,
7.06400028],
[7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,
7.05692568],
[7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,
7.04985815],
...,
[7.04988652, 7.04279774, 7.03571603, ..., 7.0286414 , 7.03571603,
7.04279774],
[7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,
7.04985815],
[7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,
7.05692568]])
이걸 이제 matplotlib
을 이용해서 시각화할 수 있당
%matplotlib inline
import matplotlib.pyplot as plt
plt.imshow(z, cmap=plt.cm.gray) #inshow = 이미지 표시에 사용, cmap는 이미지를 어떤 색상 맵으로 표현할지 지정, plt.cm.gray = 회색조 색상 맵 사용
plt.colorbar() # 색상 척도를 이미지 옆에 표시
plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values") # title함수 = 그래프의 제목 설정
output
np.where
= 파이썬 삼항연산 (<참일때 식> if <참 거짓 판단 식> else <거짓일 때 식>) 에 대응되는 넘파이 함수임
ex) cond이 true이면 xarr원소를, 그렇지 않으면 yarr 원소를 얻기를 원한다
배열 준비
xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
cond = np.array([True, False, True, True, False])
리스트 축약 이용하기
[(x if c else y) for x, y, c in zip(xarr, yarr, cond)]
output
[1.1, 2.2, 1.3, 1.4, 2.5]
리스트 축약 방법은 계산이 느려지고 복잡하다 !!
이럴때 np.where
을 써서 간단히 계산해보자
result = np.where(cond, xarr, yarr)
result
output
array([1.1, 2.2, 1.3, 1.4, 2.5])
그리고 np.where
의 두번째, 세번째 인자는 배열일 필요가 없다 ! 스칼라여도 됨
ex) 4 x 4 무작위 배열에서 음수이면 -2, 그렇지 않으면 2를 지정
arr = np.random.randn(4, 4)
arr
output
array([[-0.34791215, 0.15634897, 1.23029068, 1.20237985],
[-0.38732682, -0.30230275, -1.04855297, -1.42001794],
[-1.70627019, 1.9507754 , -0.50965218, -0.4380743 ],
[-1.25279536, 0.77749036, -1.61389785, -0.21274028]])
np.where 쓰기
np.where(arr < 0, -2, 2)
output
array([[-2, 2, 2, 2],
[-2, -2, -2, -2],
[-2, 2, -2, -2],
[-2, 2, -2, -2]])
std
, sum
, mean
과 같은 함수들로 수학 계산을 할 수 있다 ~~
(배열 준비)
arr = np.random.randn(5, 4)
arr
output
array([[-1.63019835, 0.46278226, -0.90729836, 0.0519454 ],
[ 0.72909056, 0.12898291, 1.13940068, -1.23482582],
[ 0.40234164, -0.68481009, -0.87079715, -0.57884966],
[-0.31155253, 0.05616534, -1.16514984, 0.90082649],
[ 0.46566244, -1.53624369, 1.48825219, 1.89588918]])
mean 함수 쓰기
arr.mean()
output
-0.059919320352960825
이렇게도 쓸 수 있따 ~
np.mean(arr)
output
-0.059919320352960825
sum 함수 쓰기
arr.sum()
output
-1.1983864070592165
sum 같은 메소드는 선택인자로 축(axis =
)를 가질 수 있음. axis = 0
은 다른 축은 고정시키고 첫번째 축(x축) 값에 대해서만 계산하라는 뜻
arr.sum(axis=0)
output
array([-0.34465624, -1.57312327, -0.31559248, 1.03498557])
cumsum
, cumprod
는 집계를 반환하지 않고 집계 중간값이 포함된 같은 크기의 배열을 반환
arr = np.arange(8)
arr
output
array([0, 1, 2, 3, 4, 5, 6, 7])
cumsum 메소드 쓰기
arr.cumsum()
output
array([ 0, 1, 3, 6, 10, 15, 21, 28], dtype=int32)
배열에도 됨
arr = np.arange(9).reshape(3, 3)
arr
output
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
cumsum함수 쓰기
arr.cumsum(axis=0)
output
array([[ 0, 1, 2],
[ 3, 5, 7],
[ 9, 12, 15]], dtype=int32)
배열 준비
arr = np.random.randn(10)
arr
output
array([ 0.01050002, 1.78587049, 0.12691209, 0.40198936, 1.8831507 ,
-1.34775906, -1.270485 , 0.96939671, -1.17312341, 1.94362119])
arr이 0보다 큰 것의 갯수를 센다면?
(arr > 0).sum()
output
7
자주 사용되는 메소드로 any
와 all
이 있당
파이썬 리스트 메소드 sort
와 비슷하게 넘파이 배열도 sort
메소드를 이용해서 정렬할 수 있당
arr = np.random.randn(5)
arr
output
array([ 0.40746184, -0.76991607, 0.53924919, -0.67433266, 0.03183056])
여기서 sort()
를 쓰면
arr.sort()
arr
output
array([-0.76991607, -0.67433266, 0.03183056, 0.40746184, 0.53924919])
numpy.unique
함수를 사용해서 배열 원소 중 중복되지 않는 배열을 얻을 수 있다 !!
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
np.unique(names)
output
array(['Bob', 'Joe', 'Will'], dtype='<U4')
한 배열의 원소들이 다른 배열에 속했는지를 판단할 수 있는 함수로 np.in1d
가 있다.
values = np.array([6,0,0,3,2,5,6])
np.in1d(values, [1,2,3])
output
array([False, False, False, True, True, False, False])
넘파이는 텍스트 및 바이너리 파일로 입력과 출력을 할 수 있다 !
np.save(파일 이름, 배열)
, np.load(파일이름)
을 이용해서 불러오기를 한다.
np.save
arr = np.arange(10)
np.save('examples/array_save', arr)
np.load
arr1 = np.load('examples/array_save.npy')
arr1
output
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
배열에 접근하려면 저장할 때 사용한 열쇠(key)를 이용해서 사진 형식으로 부름
arr2['a']
output
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])