학부 강의 노트/기상 인공지능 특론

넘파이(NumPy) 요약

airmaster 2021. 11. 22. 12:10
728x90

파이썬 리스트는 활용도가 높지만, 빅데이터 처리에는 충분하지 않다. 

파이썬의 리스트에서는 데이터가 비연속적인 위치에 저당되므로 대량의 데이터 처라에 불리함. 

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')

 

 

 

728x90