파이썬 리스트는 활용도가 높지만, 빅데이터 처리에는 충분하지 않다.
파이썬의 리스트에서는 데이터가 비연속적인 위치에 저당되므로 대량의 데이터 처라에 불리함.
C언어 스타일의 2차원 배열은 데이터들이 연속적인 위치에 저장되어 효율적으로 처리할 수 있음. 왜냐하면 연속적으로 데이터가 저장되어 있어야 다음 데이터를 찾기 쉽기 때문.
NumPy(Numerical Python):
과학/공학 분야에서 사용되는 파이썬 라이브러리
넘파이 API는 Pandas, SciPy, Matplotbli, scikit-learn 등의ㅐ 패키지에서 사용됨.
훈련샘플은 2차원, 3차원 다차원 행렬안에 저장됨.
행렬에서 삭제, 분리, 추가 등의 조작은 반드시 넘파이를 사용
넘파이 불러오기
>>> import numpy as np
배열 생성하기
배열은 넘파이의 핵심 데이터 구조
배열의 요소는 모두 동일한 타입
배열의 랭크(rank)는 차원 수
배열의 형상(shape)은 각 차원 및 항목 수
** 1차원 배열은 하나의 축만 가지고 있고, 2차원 배열은 2개의 축을 가진다.
배열생성은 array 함수 사용
a = np.array([1,2,3]) ## 1차원
# a: 배열 객체
# np.arry: 생성자 함수
# ([1,2,3]) : 파이썬 리스트
>>> a
array([1,2,3])
>>> a[0]
1
>>> b = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> b
arrary([[1,2,3],
[4,5,6],
[7,8,9]])
>>> b[0][2]
3
배열의 속성
넘파이 클래스 ndarray의 속성들
ndim : 축의 갯수, 2차원이면 ndim=2
shape: 배열의 형상, 정수 튜플로 나나냄. n행, m열의 경 (n,m)
size: 배열 내 요소들의 총 갯수
dtype: 배열 요소의 자료형,. numpy.int32, numpy.int16, numpy.float64 등
itemsize: 배열을 이루는 요소의 크기. 단위는 바이트. float64는 itemsize=8
data: 실제 데이터가 저장되는 메모리 블럭 주소
넘파이 배열 자료형 지정:
>>> dtype = np.int32 또는 dtype="np.int32"
>>> a=np.array([[0,1,2],
[3,4,5],
[6,7,8]])
>>> a.shape # 배열의 형상
(3,3)
>>> a.ndim # 배열의 차원 수
2
>>> a.dtype # 요소의 자료형
dtype('int32')
>>> a.itemsize # 요소 한개의 크기
8
>>> a.size # 전체 요소 수
9
1 또는 0으로 채워진 배열 생성 (주로 배열 초기화에 사용됨)
>>> np.zeros((3,4))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>> np.ones((3,4))
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
>>> np.ones((3,4), dtype=np.int32)
array([[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]])
>>> np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
>>> x = np.ones(5, dtype=np.int64)
>>> x
array([1, 1, 1, 1, 1], dtype=int64)
연속되는 값으로 배열 생성하기
np.arange(start, stop, step)
>>> x = np.ones(5, dtype=np.int64)
>>> x
array([1, 1, 1, 1, 1], dtype=int64)
>>> np.arrange(5)
AttributeError: module 'numpy' has no attribute 'arrange'
>>> np.arange(5)
array([0, 1, 2, 3, 4])
>>> np.arange(1,6)
array([1, 2, 3, 4, 5])
>>> np.arange(1,6)
array([1, 2, 3, 4, 5])
>>> np.arange(1,10,2)
array([1, 3, 5, 7, 9])
np.linspace(start, stop, num)
start: 시작값
stop: 종료값
num: 갯수
>>> np.linspace(0,10,100)
array([ 0. , 0.1010101 , 0.2020202 , 0.3030303 , 0.4040404 ,
0.50505051, 0.60606061, 0.70707071, 0.80808081, 0.90909091,
1.01010101, 1.11111111, 1.21212121, 1.31313131, 1.41414141,
1.51515152, 1.61616162, 1.71717172, 1.81818182, 1.91919192,
2.02020202, 2.12121212, 2.22222222, 2.32323232, 2.42424242,
2.52525253, 2.62626263, 2.72727273, 2.82828283, 2.92929293,
3.03030303, 3.13131313, 3.23232323, 3.33333333, 3.43434343,
3.53535354, 3.63636364, 3.73737374, 3.83838384, 3.93939394,
4.04040404, 4.14141414, 4.24242424, 4.34343434, 4.44444444,
4.54545455, 4.64646465, 4.74747475, 4.84848485, 4.94949495,
5.05050505, 5.15151515, 5.25252525, 5.35353535, 5.45454545,
5.55555556, 5.65656566, 5.75757576, 5.85858586, 5.95959596,
6.06060606, 6.16161616, 6.26262626, 6.36363636, 6.46464646,
6.56565657, 6.66666667, 6.76767677, 6.86868687, 6.96969697,
7.07070707, 7.17171717, 7.27272727, 7.37373737, 7.47474747,
7.57575758, 7.67676768, 7.77777778, 7.87878788, 7.97979798,
8.08080808, 8.18181818, 8.28282828, 8.38383838, 8.48484848,
8.58585859, 8.68686869, 8.78787879, 8.88888889, 8.98989899,
9.09090909, 9.19191919, 9.29292929, 9.39393939, 9.49494949,
9.5959596 , 9.6969697 , 9.7979798 , 9.8989899 , 10. ])
배열 정렬
>>> arr = np.array([2,1,5,3,7,4,6,8])
>>> np.sort(arr)
배열 합치기
array([1, 2, 3, 4, 5, 6, 7, 8])
>>> x=np.array([[1,2],[3,4]])
>>> y=np.array([[5,6],[7,8]])
>>> np.concatenate((x,y), axis=1)
array([[1, 2, 5, 6],
[3, 4, 7, 8]])
2개 배열 수직으로 쌓기
np.concatenate(), vstack(), hstack() 사용해도 됨.
>>> np.vstack((x,y))
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
>>> np.vstack(x,y)
TypeError: _vhstack_dispatcher() takes 1 positional argument but 2 were given
>>> np.hstack((x,y))
array([[1, 2, 5, 6],
[3, 4, 7, 8]])
배열 형태 변환
일반적으로 딥러닝은 2차원 입력이어야 한다.
따라서, 1차원 자료를 2차원으로 변환해야
reshape(): 행렬 데이터 갯수는 그대로, 차원만 변경함.
new_array = old_array.reshape((2,3))
new_array: 새로운 배열
old_array: 원래 배열
(2,3): 새 배열 형상
>>> a = np.arange(12)
>>> a.shape
(12,)
>>> a.reshape(3,4) # 3x4 행렬로 변환
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a.reshape(6,-1) #인수가 -1 인 경우, 데이터 갯수에 맞춰서 자동으로 배열형태 결정함.
array([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11]])
다차원 배열 평탄화
다차원 배열 --> 1차원으로
flatten() 사용 (ravel() 사용하면 view 만 변경되므로 주의.)
>>> y = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
>>> y.flatten()
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
>>> a = y.flatten()
>>> a[0]= 99
>>> print(a)
[99 2 3 4 5 6 7 8 9 10 11 12]
>>> print(y)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
배열 분할(슬라이싱)
넘파이 배열을 자르는 메소드는 split()
세로로 자르려면 axis=1,가로면 axis=0
>>> array= np.arange(30).reshape(-1,10)
>>> array
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]])
>>> array= np.arange(30).reshape(-1,10)
>>> array
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]])
>>> arr1,arr2 = np.split(array, [3], axis=1)
>>> arr1
array([[ 0, 1, 2],
[10, 11, 12],
[20, 21, 22]])
>>> arr2
array([[ 3, 4, 5, 6, 7, 8, 9],
[13, 14, 15, 16, 17, 18, 19],
[23, 24, 25, 26, 27, 28, 29]])
배열에 새로운 축 추가하기
np.newaxis, np.expand_dims를 사용하여 기존 배열의 크기를 증가시킬 수 있음
np.newaxis를 사용할 때 마다 차원이 1차원 증가
>>> a = np.array([1,2,3,4,5,6])
>>> a.shape
(6,)
>>> a1=a[np.newaxis, :]
>>> a1.shape
(1, 6)
>>> a2=a[:, np.newaxis]
array([[1],
[2],
[3],
[4],
[5],
[6]])
>>> a2.shape
(6, 1)
np.expand_dims() 를 사용하여 지정된 위치에 새 축을 삽입하여 배열 확장 가능
>>> b = np.expand_dims(a, axis=1)
>>> b
array([[1],
[2],
[3],
[4],
[5],
[6]])
>>> b.shape
(6, 1)
인덱싱과 슬라이싱
>>> ages = np.array([18,19, 25, 30, 28])
>>> ages[1:3] # index 1~2
array([19, 25])
>>> ages[:2] # index 0~1
array([18, 19])
>>> y = ages > 20 # 논리 인덱싱
>>> y
array([False, False, True, True, True])
>>> ages[ages > 20] ## 20 이상을 뽑아낼 때
array([25,30,28])
2차원 배열의 인덱싱
2차원 배열 인덱싱/슬라이싱은 가장 많이 사용됨. 연습 필요.
>>> a = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a[0,2]
3
>>> a[0][2]
3
>>>
>>> a[0,0] = 12
>>> a
array([[12, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]])
2차원 배열 슬라이싱
>>> a[0:2, 1:3]
array([[2, 3],
[5, 6]])
>>> a[0]
array([1,2,3])
>> a[1,1:3]
array([5,6])
얕은 복사와 깊은 복사
넘파이 함수, 인덱싱, 슬라이싱 연산자는 데이터 복사 필요없이 view 만 변환
view에서 데이터 수정하면 원본 배열도 수정됨.
얕은 복사 예 ... b가 변하면 원본 a도 변한다.
>>> a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
>>> b = a[0,:]
>>> b
array([1, 2, 3, 4])
>>> b[0] = 99
>>> b
array([99, 2, 3, 4])
>>> a
array([[99, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
깊은 복사 예 ... b2는 변해도 원본 a는 변하지 않는다.
>>> b2 = a.copy()
>>> b2
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> b2[0] = 88
>>> b2
array([[88, 88, 88, 88],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> a
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
기본 배열 연산
>>> arr1 = np.array([[1,2],[3,4],[5,6]])
>>> arr2 = np.array([[1,1],[1,1],[1,1]])
>>> results = arr1 + arr2
>>> results
array([[2, 3],
[4, 5],
[6, 7]])
>>> arr1**2
array([[ 1, 4],
[ 9, 16],
[25, 36]], dtype=int32)
>>> arr1.sum()
21
>>> arr1.min()
1
>>> arr1.max()
6
>>> arr1.mean(axis=0) # 특정 열에서의 모든 행의 값을 사용해서 계산
array([3., 4.,])
>>> arr1.mean(axis=1) # 특정 열에서의 모든 열의 값을 사용해서 계산
array([1.5, 3.5, 5.5]
>>> print(arr1.T) # 전치행렬
>>> arr1*arr2
array([[1, 2],
[3, 4],
[5, 6]])
>>> arr1 = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> arr2 = np.array([[2,2],[2,2],[2,2]])
>>> arr1 @ arr2 ## 내적 (1번째 열, 2번째 행 갯수 일치해야)
array([[12, 12],
[30, 30],
[48, 48]])
난수 생성
>>> np.random.seed(100) # 이후 아래 명령어 수행해야
>>>np.radom.rand(5)
>>> np.radom.rand(5,3)
>>> np.radom.randit(1,7,size=10)
>> > np.random.randn(5) ## 정규분포 난수 생성
a = np.random.normal(loc=0.0, scale=1.0, size=None)
loc: 평균
scale: 표준편차
size: 배열의 차원
>> mu, sigma = 0, 0.1
>> np.random.normal(mu, sigma, 5)
array([-0.17497655, 0.03426804, 0.11530358, -0.0252436 , 0.09813208])
고유 항목과 갯수 구하기
>>> a = np.array([11,11,12,14,13, 15, 16, 17, 12, 13, 11, 14, 18, 19, 20])
>>> unique_values = np.unique(a)
>>> unique_values
array([11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
>>> uniuqe_values, indices_list = np.unique(a, return_index=True)
>>> print(indices_list)
[ 0 2 3 4 5 6 7 8 12 13 14]
>>> unique_values, occurrence_count = np.unique(a, return_counts=True)
>>> print(occurrence_count)
[3 2 2 2 1 1 1 1 1 1]
파일 입출력 (.csv)
Pandas 를 사용
read_csv()를 호출하면 반환되는 객체의 values에 넘파이배열로 저장됨.
>>> import numpy as np
>>> import pandas as pd
>>> x= pd.read_csv('example.csv', header=0).values
>>> print(x)
>>> x= pd.read_csv('example.csv', usecols=['col1','col2']).values
>>> print(x)
>>> df = pd.DataFrame(a)
>>> print(df)
>> df.to_csv('out.csv')