Home Numpy
Post
Cancel

Numpy

Numpy

numpy는 Numerical python의 약자로 다차원 연산을 위한 많은 도구를 제공해주는 라이브러리이다.

  • List에 비해 빠르고 메모리 측면에서 효율적이다.
  • 반복문 없이 데이터 배열에 대한 처리를 지원한다.
  • 선현 대수와 관련된 다양한 기능을 제공한다.

List로 배열 만들기

numpy의 array함수에 list를 넣어주면 ndarray객체로 변환해준다.

1
2
3
4
5
6
import numpy as np # np라는 이름으로 import하는것이 관례

a = np.array([1,2,3])
b = np.array([2,4,8], float) # data type을 명시할 수 있음

type(a) # numpy.ndarray

numpy의 배열은 같은 자료형을 가지는 배열이다. 같은 자료형들만 넣을 수 있다. 하지만 자료형을 명시하면 적절하게 형변환해 같은 자료형으로 들어간다. 다차원 배열은 리스트를 중첩해서 생성할 수 있다.

1
2
3
import numpy as np

c = np.array([[1,2,3],[2,4,8]])

rank, shape

numpy에서 rank는 배열이 몇 차원을 나타내며 shape는 각 차원의 크기담고 있는 튜플을 반환한다.(dimension 구성을 반환) c.shape # (2,3) shape의 결과로 나온 튜플을 보면 2차원이며 1차원의 크기는 2, 2차원 배열의 크기는 3인것을 알 수 있다. rank(차원은) ndim으로 알 수 있다.

  • rank에 따라 불리는 이름
    1. rank : 0 → scalar
    2. rank : 1 → vector
    3. rank : 2 → matrix
    4. rank : n → n-tensor

numpy 함수를 사용해 배열만들기

list를 사용하지않고 numpy의 함수를 사용해 배열을 생성할 수 있다.

  1. zeros((n,m,..))

    n *m *.. 크기의 0으로 채워진 배열을 만든다.

    1
    2
    3
    4
    5
    6
    7
    
     import numpy as np
        
     a = np.zeros((2,3))
     print(a)
     ## output
     #  [[0. 0. 0.]
     #  [0. 0. 0.]]
    
  2. ones((n,m,..))

    n * m *.. 크기의 1로 채워진 배열을 만든다.

    1
    2
    3
    4
    5
    
     a = np.ones((2,3))
     print(a)
     ## output
     #  [[1. 1. 1.]
     #  [1. 1. 1.]]
    
  3. full((n,m,..), num)

    n * m * .. 크기의 num으로 채워진 배열을 만든다.

    1
    2
    3
    4
    5
    
     a = np.full((2,3),100)
     print(a)
     ## output
     #  [[100 100 100]
     #  [100 100 100]]
    
  4. eye(n), identity(n)

    n * n 크기의 단위행렬을 만든다. eye의 경우 아래의 코드처럼 nn뿐만 아니라 nm행렬을 만들 수 있고 k를 사용해 대각선의 시작 위치를 지정할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
     a = np.identity(3) # iden
     print(a)
     ## output
     #  [[1. 0. 0.]
     #   [0. 1. 0.]
     #   [0. 0. 1.]]
     a = np.eye(N=3, M=5)
     print(a)
     ## output
     #  [[1. 0. 0. 0. 0.]
     #   [0. 1. 0. 0. 0.]
     #   [0. 0. 1. 0. 0.]]
     a = np.eye(N=3, M=5, k=2)
     print(a)
     ## output
     #  [[0. 0. 1. 0. 0.]
     #   [0. 0. 0. 1. 0.]
     #   [0. 0. 0. 0. 1.]]
    
  5. random.random((n,m,..)), random.(sampling)(..

    n * m *.. 크기의 random으로 채워진 배열을 만든다. 데이터 분포에 따른 sampling으로 array를 만들 수있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
     a = np.random.random((2,3))
     print(a)
     ## output
     #  [[0.56836423 0.27221542 0.24358307]
     #   [0.49611743 0.69032221 0.64952519]]
        
     a = np.random.uniform(0,1,10).reshape(2,5) # 균등 분포
     ## output
     #  [[0.45164578 0.2673851  0.82372912 0.36826149 0.02301544]
     #   [0.59698836 0.66194833 0.77225828 0.10904343 0.48492763]]
     a = np.random.normal(0,1,10).reshape(2,5) # 정규 분포
     ## output
     #  [[ 0.55986047  0.38099485  0.16202188  0.8722009  -0.21303353]
     #   [ 2.34541515  0.37723978  0.91292917  0.67820507  0.17847015]]
        
    
  6. arange(n) , arange(start, end, step)

    범위의 원소를 가지는 array 배열을 만든다.

    1
    2
    3
    4
    5
    6
    7
    
     np.arange(10)
     # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
     np.arange(0, 10, 0.5)
     # array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. , 6.5, 7. , 7.5, 8. , 8.5, 9. , 9.5])
     np.arange(10).reshape(-1,5)
     # array([[0, 1, 2, 3, 4],
     #        [5, 6, 7, 8, 9]])
    
  7. something_like

    ones, zeros등을 같이 사용하며 어떤 array와 같은 shape를 가진 0, 1로 채원진 배열을 만들어준다.

    1
    2
    3
    4
    
     a = np.arange(10).reshape(-1,5)
     np.ones_like(a)
     # array([[1, 1, 1, 1, 1],
     #        [1, 1, 1, 1, 1]])
    
  8. diag(ndarray)

    array의 대각 행렬 값을 추출한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
     import numpy as np
        
     a = np.arange(12).reshape(-1,4)
     print(a)
     ## output
     #  [[ 0  1  2  3]
     #   [ 4  5  6  7]
     #   [ 8  9 10 11]]
     print(np.diag(a))
     ## output
     #  [ 0  5 10]
     print(np.diag(a, k=2))
     ## output
     #  [2 7]
    
  9. vstack, hstack, concatenate

    array를 합칠 수 있다.

    • vstack : 수직으로 붙히기

      1
      2
      3
      4
      5
      6
      7
      
        import numpy as np
              
        a = np.array([1,2,3])
        b = np.array([4,5,6])
        np.vstack((a,b))
        # array([[1, 2, 3],
        #        [4, 5, 6]])
      
    • hstack : 수평으로 붙히기

      1
      2
      3
      4
      5
      6
      7
      8
      
        import numpy as np
              
        a = np.array([[1],[2],[3]])
        b = np.array([[4],[5],[6]])
        np.hstack((a,b))
        # array([[1, 4],
        #        [2, 5],
        #        [3, 6]])
      
    • concatenate : axis를 기준으로 배열을 합칠 수 있다. axis는 두 배열을 붙혔을 때 결과값의 axis라고 생각하면 편하다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
        import numpy as np
              
        a = np.array([[1,2,3]])
        b = np.array([[4,5,6]])
        np.concatenate((a,b),axis=0)
        # array([[1, 2, 3],
        #        [4, 5, 6]])
              
        a = np.array([[1,2],[3,4]])
        b = np.array([5,6])
        b = b[np.newaxis, :]  # 두 배열의 축을 맞춰주기위해 b에 축을 하나 추가
        np.concatenate((a,b.T),axis=1) # b.T는 b를 transpose한것
        # array([[1, 2, 5],
        #        [3, 4, 6]])
      

배열 접근

a[i][j]와 같이 C, C++처럼 배열을 사용할 수 있고, a[i, j]와 같이 사용도 가능하다.

1
2
3
4
5
6
a = np.array([[2,3,4],[4,5,6]])
print(a[1][1])
print(a[1,1])
## output
#  5
#  5

자료형

numpy의 자료형과 pyhton기본 자료형의 차이는 세부 비트이다. 세부 비트는 자료형의 비트 크기를 나타낸다.

  • int8, int16, int32, int64
  • uint8, uint16, uint32, uint64
  • float16, float32, float64, float128
  • complex64, complex128, complex256
  • bool
  • string
  • object
  • unicode

배열의 data type을 알기 위해서는 dtype를 사용하면 된다.

1
2
3
4
5
6
7
8
9
a = np.array([2,3,4],[4,5,6]], dtype=np.float32)
print(a.dtype)
## output
#  float32

b = np.ones((2,2), np.int64)
print(b.dtype)
## output
#  int64

dtype는 생략해도되고 ones의경우 기본 float32로 배열이 생성되는데 int타입을 지정하면 int타입으로 배열이 생성된다. python의 경우 숫자 자료형의 최대 최소가 정해져있지 않지만 numpy가 c로 만들어져있어 자료형의 크기가 있어야 한다고한다.


reshape

reshape함수는 배열의 shape를 변경하는경우 사용하는 함수이다.

reshape(배열, shape), reshape(shape)처럼 사용할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np

a_list = [1,2,3,4,5,6]
a = np.reshape(a_list,(2,3))
print(a)
## output
#  [[1 2 3]
#   [4 5 6]]

b = np.reshape(a,(3,2))
print(b)
## output
#  [[1 2]
#   [3 4]
#   [5 6]]

c = a.reshape(1,2,3)  ## b와 다르게 ndarry a의 reshape를 호출 
print(c)
## output
#  [[[1 2 3]
#   [4 5 6]]]

c의 경우 shape를 2,3에서 1,2,3으로 바꾸어 가장 밖에 대괄호가 하나 추가된것을 볼 수 있다.

reshape의 경우 해당 바꾸려는 shape로 변경할 수 없는경우 (원소의 개수가 달라지는 경우) Error가 발생한다. reshape(-1, 2) 와 같이 -1을 넣으면 size를 기반으로 자동으로 계산해 값이 들어간다.


flatten

flatten은 다차원 array를 1차원으로 변환해준다.

1
2
3
4
5
6
import numpy as np

a_list =[[1,2,3],[4,5,6]]
a = np.array(a_list)
a.flatten()
# array([1, 2, 3, 4, 5, 6])

슬라이싱

Numpy도 리스트처럼 슬라이싱이 가능하다. 다차원의 경우 각 차원별로 슬라이싱을 어떻게 할지 명확하게 해야한다. 특정 차원의 슬라이싱을 작성하지않으면 [:]를 한것과 같은 결과를 얻을 수 있다.

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
import numpy as np

a = np.array([[1,2,3,4,5],[2,4,6,8,10],[3,6,9,12,15]])
print(a[1:,2:3])
## output
#  [[6]
#   [9]]
print(a[:, 1:3])
## output
#  [[2 3]
#   [4 6]
#   [6 9]]
print(a[:3, 4]) # 범위를 지정한것과 4처럼 범위를 지정하지 않는것은 dimension 다르다.
## output
#  [ 5 10 15]
print(a[:3, 4:5]
## output
# [[5]
#  [10]
#  [15]]
print(a[:,:])
## output
#  [[ 1  2  3  4  5]
#   [ 2  4  6  8 10]
#   [ 3  6  9 12 15]]
print(a[:-1,:-1])
## output
#  [[1 2 3 4]
#   [2 4 6 8]]

list의 슬라이싱과 똑같이 동작하는것을 확인할 수있다. 콤마(,)를 기준으로 각 차원의 슬라이싱을 어떻게 할지 작성할 수 있다. 슬라이싱을 통해 얻은 배열의 경우 원본 배열의 부분배열이 나오는것이다. 복사된 새로운 배열이 나오는것이 아니기 때문에 슬라이싱한 결과를 변경하면 원본 배열도 변경된다. 슬라이싱한 결과를 copy()함수를 사용하면 복사본이 반환되기 때문에 슬라시이한 결과를 변경할 필요가 있는경우 상황에 따라 적절하게 copy함수를 사용해야한다.

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

a = np.array([[1,2,3,4,5],[2,4,6,8,10],[3,6,9,12,15]])
b = a[1:,2:3] # 만약 b = a[1:,2:3].copy()로 했다면 b의 값을 바꾸어도 원본 배열이 안바뀜

b[0][0] = 99
print(a)
## output
#  [[ 1  2  3  4  5]
#   [ 2  4 99  8 10]
#   [ 3  6  9 12 15]]

또한 ndarray[start : stop : step] 처럼 step을 작성할 수도있다.


인덱싱

  • fancy indexing

    numpy의 경우 fancy indexing이라고 조회하고 싶은 index를 list로 전달할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
      import numpy as np
        
      a = np.array([[1,2], [3, 4], [5, 6]])
      print (a[[0, 1, 2], [0, 1, 0]])
      ## output
      #  [1,4,5]
      b = np.array([0,1,2])
      c = np.array([0,1,0])
      print(a[b,c])  # 같은 결과가 나옴
    

    위의 a인덱스 접근은 가장 처음 축에서 0, 1, 2 번을, 2번째 축에서 0, 1, 0을 접근하겠다는 뜻으로 [0,0], [1,1], [2,0]에 들어있는 1,4,5가 출력된 것을 알 수 있다. fancy indexing은 새로운 배열을 만들기 때문에 원본 배열에 영향을 끼치지 못한다.

  • boolean indexing

    배열의 각 요소들 중 특정 조건을 만족하는 요소만 추출하는것을 도와준다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
      import numpy as np
        
      a = np.array([[1,2,3,4,5], [2,4,6,8,16], [3,6,9,12,15]])
      b = (a % 2 == 0) # 조건의 True False를 같은 rank, shape의 배열로 반환
      print(b)
      ## output
      #  [[False  True False  True False]
      #   [ True  True  True  True  True]
      #   [False  True False  True False]]
      print (a[b])  # bool 결과에서 True로만 구성된 rank 1인 배열 반환
      ## output
      #  [ 2  4  2  4  6  8 16  6 12]
        
      print (a[a % 2 == 0])
      ## output
      #  [ 2  4  2  4  6  8 16  6 12]
    

연산

  • axis

    모든 operation function을 실행할 때 기준이 되는 dimension축(shape의 결과로 나온 튜플에서 인덱스가 axis라고 생각하면 될듯)

  • sum

    list의 sum과 같이 원소의 합을 구할 수 있다.

    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
    32
    
      import numpy as np
        
      a = np.arange(36).reshape(3,3,4)
      # [[[ 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]
      #   [32 33 34 35]]]
        
      a.sum()
      # 630 
        
      a.sum(axis=2)
      # [[  6  22  38]
      #  [ 54  70  86]
      #  [102 118 134]]
        
      print(a.sum(axis=1))
      # [[12 15 18 21]
      #  [48 51 54 57]
      #  [84 87 90 93]]
        
      print(a.sum(axis=0))
      # [[36 39 42 45]
      #  [48 51 54 57]
      #  [60 63 66 69]]
    
  • mean, std

    평균 또는 표준 편차를 구할 수 있다.

  • 사칙연산

    +, -, *, /연산을 지원하지만 shape가 같은 경우 element-wise연산이 실행되어 같은 위치의 element끼리 연산해 결과가 나온다.

  • Dot product

    행렬곱 연산

    1
    2
    3
    4
    5
    6
    7
    
      import numpy as np
        
      a = np.arange(1,7).reshape(2,3)
      b = np.arange(7,13).reshape(3,2)
      a.dot(b)
      # array([[ 58,  64],
      #        [139, 154]])
    
  • transpose

    전치행렬을 구해준다. a.transponse() 또는 a.T 와 같이 사용한다.


브로드캐스팅

shape이 다른 배열 간 연산을 지원하는 기능이다. scalar와 vector연산 혹은 vector와 matrix의 연산에서 브로드캐스팅이 일어난다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import numpy as np

a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = np.array([1,2,3])

a * 3 # a의 모든 원소에 3이 곱해진 결과가 나옴
# array([[ 3,  6,  9],
#        [12, 15, 18],
#        [21, 24, 27]])

a + b # a의 각 행에 1,2,3을 더한 결과가 나옴
# array([[ 2,  4,  6],
#        [ 5,  7,  9],
#        [ 8, 10, 12]])

c = np.array([[1],[2],[3],[4]])
d = np.array([1,2,3])
c + d
# array([[2, 3, 4],
#        [3, 4, 5],
#        [4, 5, 6],
#        [5, 6, 7]])

comparisons

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np

a = np.array([1,2,3])
b = np.array([4,5,1])
a>b
# array([False, False,  True])

(a>b).any()  # any는 or연산
# True

(a>b).all() # all은 and연산
# False

a>0
# array([ True,  True,  True])

np.logical_and(a>0,a<3) # 둘다 True면 True
# array([ True,  True, False])

np.logical_or(a>0, a<3)
# array([ True,  True,  True])
  • np.where

    np.where(condition, TRUE, FALSE) 와 같이 사용하며 condition이 True일 때는 해당 위치에 TRUE에 작성된 값, False일 때는 해당 위치에 FALSE에 작성된 값을 가진 array가 나온다.

    TRUE, FALSE를 작성하지 않으면 index를 반환한다.

    1
    2
    3
    4
    5
    6
    7
    8
    
      import numpy as np
        
      a = np.array([1,2,3])
      np.where(a>2, 3, 2) 
      # array([2, 2, 3])
        
      np.where(a>2)
      # (array([2], dtype=int64),)
    
  • isnan, isfinite

    is 난은 nan일 경우 True, isfinite는 finite(inf나 nan이 아닌 경우) 인경우 True

    1
    2
    3
    4
    5
    6
    7
    8
    
      import numpy as np
        
      a = np.array([1, np.NaN, np.Inf])
      np.isnan(a)
      # array([False,  True, False])
        
      np.isfinite(a)
      # array([ True, False, False])
    
  • argmax, argmin

    최대값 초소값의 index를 반환한다. axis를 사용해 축을 지정할 수 있다.

  • argsort

    오름차순이 되도록 하는 index들을 반환한다.

    1
    2
    3
    4
    5
    
      import numpy as np
        
      a = np.array([1,6,3,2,6,843,123,1235,32])
      a.argsort()
      # array([0, 3, 2, 1, 4, 8, 6, 5, 7], dtype=int64)
    

numpy i/o

  • loadtxt, savetxt

    text type의 데이터를 읽고 저장하는 기능

    1
    2
    3
    
      a = np.loadtxt("test.txt")
      a_int = a.astype(int) # 타입 변환
      np.savetxt("text_save.csv",a_int, delimiter=",") # csv로 저장
    
  • load, save

    numpy object그대로 저장, (pickle 형태)

    1
    2
    
      npy_array = np.load(file="test.npy")
      np.save("test", arr = npy_array)
    
This post is licensed under CC BY 4.0 by the author.