Post

[Numpy] Numpy 기초

  • Python Library 중 하나인 Numpy에 대한 기초 정리이다.
  • Numpy는 대량의 데이터를 처리하는데 처리 속도가 빨라 데이터 분석에서 많이 활용되고 있다.

Numpy

  • Numerical Python의 줄임말
  • 빠른 수치 계산을 위해 C언어로 만들어진 Python 라이브러리
  • 백터와 행렬 연산에 매우 편리한 기능들을 제공
  • 데이터분석용 라이브러리인 PandasMatplotlib의 기반으로 사용되기도 함
  • Numpy는 np.array 함수를 활용하여 배열을 생성함
  • Numpy는 하나의 데이터 type 만 배열에 넣을 수 있음 -> List와 가장 큰 차이점

1. 라이브러리 불러오기

  • Numpy 라이브러리는 일반적으로 np 별칭을 붙여 불러온다.
1
import numpy as np

2. 배열 만들기

  • 편의를 위해 Numpy 배열을 그냥 배열이라고 부르자.

용어 정의

array

[용어]

  • axis: 배열의 각 축
  • rank: 축의 개수
  • shape: 축의 길이, 배열의 크기

[3 x 4 배열의 경우]

  • axis 0 과 axis 1 을 갖는 2차원 배열
  • rank 2 array
  • shape는 (3, 4)

배열 만들기

  • np.array() 함수를 사용해서 배열을 만듦.
  • 리스트로부터 배열을 만들거나, 머신러닝 관련 함수 결과값이 배열이 됨.
1
2
3
4
5
6
7
8
9
# 1차원 리스트
a = [1, 2, 3, 4, 5]

# 배열로 변환
b = np.array(a)

# 확인
print('list :', a)
print('np.array :', b)
1
2
list : [1, 2, 3, 4, 5]
np.array : [1 2 3 4 5]
1
2
3
4
5
6
7
8
a2 = [[1.5, 2.5, 3.2], 
      [4.2, 5.7, 6.4]]

# 배열로 변환
b2 = np.array(a2)

# 확인
print(b2)
1
2
[[1.5 2.5 3.2]
 [4.2 5.7 6.4]]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 3차원 리스트
# a3 = [[[1, 3, 1], [4, 7, 6], [8, 3, 4]], [[6, 2, 4], [8, 1, 5], [3, 5, 9]]]
a3 = [[[1, 3, 1],
       [4, 7, 6],
       [8, 3, 4]],
      [[6, 2, 4],  
       [8, 1, 5],
       [3, 5, 9]]]

# 배열로 변환
b3 = np.array(a3)

# 확인
print(b3)
1
2
3
4
5
6
7
[[[1 3 1]
  [4 7 6]
  [8 3 4]]

 [[6 2 4]
  [8 1 5]
  [3 5 9]]]

Create Functions

1) arange
  • array의 범위를 지정하여, 값의 List를 생성하는 명령어
1
np.arange(10)
1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1
2
# (시작, 끝, step) step에 floating point도 표시가능
np.arange(0, 5, 0.5)
1
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
1
np.arange(30).reshape(5,6)
1
2
3
4
5
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]])
2) zeros
  • 0으로 가득찬 배열 생성
1
np.zeros(shape=(10,), dtype=np.int8)
1
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int8)
1
2
# 2 by 5 - zero matrix 생성
np.zeros((2,5))
1
2
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])
3) ones
  • 1로 가득찬 배열 생성
  • np.ones(shape, dtype, order)
1
np.ones(shape=(10,), dtype=np.int8)
1
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int8)
1
np.ones((2,5))
1
2
array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])
4) empty
  • shape만 주어지고 비어있는 배열 생성
  • memory initialization 이 되지 않음
1
np.empty(shape=(10,), dtype=np.int8)
1
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int8)
1
np.empty((3,5))
1
2
3
4
5
6
array([[0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
        0.00000000e+000, 0.00000000e+000],
       [0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
        0.00000000e+000, 0.00000000e+000],
       [0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
        0.00000000e+000, 1.02187024e+295]])
5) something_like
  • 기존 배열의 shape 크기 만큼 1, 0 또는 empty array를 반환
1
2
test_matrix = np.arange(30).reshape(5,6)
np.ones_like(test_matrix)
1
2
3
4
5
array([[1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1, 1]])
6) identity
  • 단위 행렬 (i 행렬)을 생성함
1
np.identity(n=3, dtype=np.int8)
1
2
3
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]], dtype=int8)
1
np.identity(5)
1
2
3
4
5
array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])
7) eye
  • 대각선이 1인 행렬, k값의 시작 index의 변경이 가능
1
np.eye(N=3, M=5, dtype=np.int8)
1
2
3
array([[1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0],
       [0, 0, 1, 0, 0]], dtype=int8)
1
np.eye(3)
1
2
3
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
1
2
# k -> start index
np.eye(3, 5, k=2)
1
2
3
array([[0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])
8) diag
  • 대각 행렬의 값을 추출함
1
2
matrix = np.arange(9).reshape(3,3)
np.diag(matrix)
1
array([0, 4, 8])
1
np.diag(matrix, k=1)
1
array([1, 5])
9) Random Sampling
  • 데이터 분포에 따른 sampling으로 array를 생성
1
2
# 균등분포
np.random.uniform(0,1,10).reshape(2,5)
1
2
array([[0.79399847, 0.78695637, 0.20878559, 0.68880039, 0.75485172],
       [0.61325652, 0.95731992, 0.51921851, 0.79268682, 0.8922863 ]])
1
2
# 정규분포
np.random.normal(0,1,10).reshape(2,5)
1
2
array([[ 0.15096311,  0.7967732 , -0.25318434,  0.73347587,  2.8557428 ],
       [ 0.9828345 ,  1.19771688, -1.66174886, -1.10692387, -0.29010521]])

배열 정보 확인

  • ndim : 배열의 차원을 반환함 (number of dimension)
  • shape : 배열의 object의 dimension 구성을 반환함
  • dtype : 배열의 data type을 반환함
  • size : data의 개수를 반환함

Axis 0의 의미

  • array.shape 의 첫 번째
  • 분석단위를 구성
  • 분석 단위 개수를 의미
1
2
3
print(b.ndim)
print(b2.ndim)
print(b3.ndim)
1
2
3
1
2
3
1
2
3
print(b.shape)
print(b2.shape)
print(b3.shape)
1
2
3
(5,)
(2, 3)
(2, 3, 3)
1
2
3
print(b.dtype)
print(b2.dtype)
print(b3.dtype)
1
2
3
int32
float64
int32
1
2
3
print(b.size)
print(b2.size)
print(b3.size)
1
2
3
5
6
18

Reshape

  • 다양한 형태(Shape)로 변환
  • 배열에 포함된 요소가 사라지지 않는 형태라면 자유롭게 변환 가능
  • 배열의 Size만 같다면 다차원으로 자유롭게 변환 가능
1
2
3
4
5
6
7
8
9
# (2, 3) 형태의 2차원 배열 만들기
a = np.array([[1, 2, 3], 
              [4, 5, 6]])

# (3, 2) 형태의 배열로 Reshape
b = a.reshape(3, 2)

# 확인
print(b)
1
2
3
[[1 2]
 [3 4]
 [5 6]]
1
2
3
4
5
# 1차원 배열로 Reshape
c = a.reshape(6)

# 확인
print(c)
1
[1 2 3 4 5 6]

-1의 편리성

  • (m, -1) 또는 (-1, n) 처럼 사용해 한 쪽만 지정할 수 있음
  • -1의 자리는 자동으로 설정 해주는 것임.
1
2
3
4
5
6
7
8
9
10
11
12
# (2, 6) 형태의 2차원 배열 만들기
a = np.array([[1, 2, 3, 4, 5, 6], 
              [7, 8, 9, 10, 11, 12]])

# reshape(m, -1)
print(a.reshape(1, -1), end='\n----------\n')

print(a.reshape(4, -1), end='\n----------\n')

# reshape(-1, m, n)
print(a.reshape(-1, 2, 3), end='\n\n')

1
2
3
4
5
6
7
8
9
10
11
12
[[ 1  2  3  4  5  6  7  8  9 10 11 12]]
----------
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
----------
[[[ 1  2  3]
  [ 4  5  6]]

 [[ 7  8  9]
  [10 11 12]]]

Flatten

  • 다차원 배열을 1차원 배열로 변환
1
2
test_matrix = [[[1,2,3,4],[1,2,5,7]], [[1,2,3,4],[1,2,5,8]]]
np.array(test_matrix).flatten()
1
array([1, 2, 3, 4, 1, 2, 5, 7, 1, 2, 3, 4, 1, 2, 5, 8])

3. 배열 인덱싱과 슬라이싱

인덱싱 (Indexing)

  • array[행, 열] 형태로 특정 위치의 요소를 조회
  • 열은 생략가능
  • 행과 열에는
    • 값, 단일 인덱스. ex) arr[2, 3]
    • 값, 여러 인덱스. ex) arr[[list], [list]]
    • 범위, 슬라이싱. ex) arr[1:5, 2:]

1) 요소 조회

1
2
3
4
5
6
7
# (3, 3) 형태의 2차원 배열 만들기
a = np.array([[1, 2, 3],
              [4, 5, 6], 
              [7, 8, 9]])

# 첫 번째 행, 두 번째 열 요소 조회
print(a[0, 1])
1
2

2) 행 조회

1
2
3
# 첫 번째, 두 번째 행 조회
# print(a[[0, 1], :])
print(a[[0, 1]])
1
2
[[1 2 3]
 [4 5 6]]

3) 열 조회

1
2
# 첫 번째, 두 번째 열 조회
print(a[:, [0, 1]])
1
2
3
[[1 2]
 [4 5]
 [7 8]]

4) 행, 열 조회

1
2
# 두 번째 행 두 번째 열의 요소 조회
print(a[[1], [1]])
1
[5]
1
2
# 세 번째 행 두 번째 열의 요소 조회
print(a[[2], [1]])
1
[8]

슬라이싱 (Slicing)

  • array[행1:행N, 열1:열N]의 형태로 지정해 그 위치의 요소를 조회
  • 조회 결과는 2차원 배열이 됨
  • 마지막 범위 값은 대상에 포함되지 않음
1
2
3
4
5
6
7
8
# (3, 3) 형태의 2차원 배열 만들기
a = np.array([[1, 2, 3],
              [4, 5, 6], 
              [7, 8, 9]])

# 첫 번째 ~ 두 번째 행 조회
# print(a[0:2, :])
print(a[0:2])        
1
2
[[1 2 3]
 [4 5 6]]
1
2
# 첫 번째 행, 첫 번째 ~ 두 번째 열 조회
print(a[0, 0:2])
1
[1 2]
1
2
# 첫 번째 ~ 세 번째 행, 두 번째 ~ 세 번째 열 조회
print(a[0:3, 1:3])
1
2
3
[[2 3]
 [5 6]
 [8 9]]
1
2
# 두 번째 ~ 끝 행, 두 번째 ~ 끝 열 조회
print(a[1:, 1:])
1
2
[[5 6]
 [8 9]]

조건 조회

  • 조건에 맞는 요소를 선택하는 방식이며, boolean index라고 부름
  • 조회 결과는 1차원 배열이 됨
1
2
3
4
5
6
# 2차원 배열 만들기
score= np.array([[78, 91, 84, 89, 93, 65],
                 [82, 87, 96, 79, 91, 73]])

# 요소 중에서 90 이상인 것만 조회
print(score[score >= 90])
1
[91 93 96 91]
  • 검색 조건을 변수로 선언해 사용할 수 있음
1
2
3
# 요소 중에서 90 이상인 것만 조회
condition = score >= 90
print(score[condition])
1
[91 93 96 91]
1
score >= 90
1
2
array([[False,  True, False, False,  True, False],
       [False, False,  True, False,  True, False]])
1
2
# 모든 요소 중에서 90 이상 95 미만인 것만 조회
print(score[(score >= 90) & (score <= 95)])
1
[91 93 91]

Fancy index

  • array를 index value로 사용해서 값을 추출하는 방법
1
2
3
a = np.array([2, 4, 6, 8])
b = np.array([0, 0 ,1, 3, 2, 1], int)    # 반드시 integer로 선언
a[b]
1
array([2, 2, 4, 8, 6, 4])
1
a.take(b)
1
array([2, 2, 4, 8, 6, 4])
  • Matrix 형태의 데이터도 가능 (많이 쓰지 않음)
1
2
3
4
a = np.array([[1,4],[9, 16]])
b = np.array([0,0,1,1,0], int)
c = np.array([0,1,1,0,1], int)
a[b,c]
1
array([ 1,  4, 16,  9,  4])

4. 배열 연산

  • Numpy는 배열간의 기본적인 사칙 연산을 지원함
  • Element-wise Operations : 배열간 shape이 같을 때 일어나는 연산 (같은 위치에 있는 값들끼리의 연산)
1
2
3
4
5
6
7
# 두 개의 (2, 2) 형태의 2차원 배열 만들기
x = np.array([[1, 2], [3, 4]])
y = np.array([[5, 6], [7, 8]])

# 확인
print(x)
print(y)
1
2
3
4
[[1 2]
 [3 4]]
[[5 6]
 [7 8]]

배열 더하기

  • + 또는 np.add() 함수를 사용
1
2
3
4
5
# 배열 더하기
print(x + y)

# 또는
print(np.add(x, y))
1
2
3
4
[[ 6  8]
 [10 12]]
[[ 6  8]
 [10 12]]

배열 빼기

  • - 또는 np.subtract() 함수를 사용
1
2
3
4
5
# 배열 빼기
print(x - y)

# 또는
print(np.subtract(x, y))
1
2
3
4
[[-4 -4]
 [-4 -4]]
[[-4 -4]
 [-4 -4]]

배열 곱하기

  • * 또는 np.multiply() 함수를 사용
1
2
3
4
5
# 배열 곱하기
print(x * y)

# 또는
print(np.multiply(x, y))
1
2
3
4
[[ 5 12]
 [21 32]]
[[ 5 12]
 [21 32]]

배열 나누기

  • / 또는 np.divide() 함수를 사용
1
2
3
4
5
# 배열 나누기
print(x / y)

# 또는
print(np.divide(x, y))
1
2
3
4
[[0.2        0.33333333]
 [0.42857143 0.5       ]]
[[0.2        0.33333333]
 [0.42857143 0.5       ]]

배열 제곱

  • ** 또는 np.power() 함수를 사용
1
2
3
4
5
# 배열 y 제곱
print(x ** y)

# 또는
print(np.power(x, y))
1
2
3
4
[[    1    64]
 [ 2187 65536]]
[[    1    64]
 [ 2187 65536]]
1
2
# 배열 제곱
print(x ** 2)
1
2
[[ 1  4]
 [ 9 16]]

배열 집계

  • np.sum() 혹은 array.sum()
    • axis = 0 : 열 기준 집계
    • axis = 1 : 행 기준 집계
    • 생략하면 : 전체 집계
  • 동일한 형태로 사용 가능한 함수 : np.max(), np.min(), np.mean(), np.std()
1
2
3
4
5
6
7
8
9
10
11
12
# array를 생성합니다.
a = np.array([[1,5,7],[2,3,8]])
print(a, end='\n\n')

# 전체 집계
print(np.sum(a), end='\n\n')

# 열기준 집계
print(np.sum(a, axis = 0), end='\n\n')

# 행기준 집계
print(np.sum(a, axis = 1))
1
2
3
4
5
6
7
8
[[1 5 7]
 [2 3 8]]

26

[ 3  8 15]

[13 13]

Dot Product

  • matrix의 기본 연산
  • dot 함수 사용
1
2
3
a = np.arange(1,7).reshape(2,3)
b = np.arange(7,13).reshape(3,2)
a.dot(b)
1
2
array([[ 58,  64],
       [139, 154]])

Transpose

  • transpose 또는 T attribute 사용
1
2
a = np.arange(1,7).reshape(2,3)
a
1
2
array([[1, 2, 3],
       [4, 5, 6]])
1
a.T
1
2
3
array([[1, 4],
       [2, 5],
       [3, 6]])

Broadcasting

  • shape이 다른 배열 간 연산을 자동으로 지원하는 기능
  • scalar - vector 외에도 vector - matrix 간의 연산도 지원
1
2
a + 3
# a - 2, a * 4, a / 2, a // 0.2, a ** 3 등등
1
2
array([[4, 5, 6],
       [7, 8, 9]])
1
2
3
test_matrix = np.arange(1,13).reshape(4,3)
test_vector = np.arange(10,40,10)
test_matrix + test_vector
1
2
3
4
array([[11, 22, 33],
       [14, 25, 36],
       [17, 28, 39],
       [20, 31, 42]])

Operation Functions

1) Concatenate

  • 배열을 합치는 함수
  • vstack : 세로로 합치기
  • hstack : 가로로 합치기
  • concatenate : axis=0 -> vstack, axis=1 -> hstack
1
2
3
4
a = np.array([1,2,3])
b = np.array([5,7,8])
c = np.vstack((a,b))
c
1
2
array([[1, 2, 3],
       [5, 7, 8]])
1
2
3
4
a = np.array([[1],[2],[3]])
b = np.array([[5],[7],[8]])
c = np.hstack((a,b))
c
1
2
3
array([[1, 5],
       [2, 7],
       [3, 8]])
1
2
3
4
a = np.array([[1, 2, 3]])
b = np.array([[5, 7, 8]])
c = np.concatenate((a,b), axis=0)
c
1
2
array([[1, 2, 3],
       [5, 7, 8]])
1
2
3
4
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
c = np.concatenate((a,b.T), axis=1)
c
1
2
array([[1, 2, 5],
       [3, 4, 6]])

5. Comparisons

All & Any

  • 배열의 데이터 전부(and) 또는 일부(or)가 조건에 만족 여부 반환
1
2
a = np.arange(10)
np.all(a>5), np.all(a<10)
1
(False, True)
1
np.any(a>5), np.any(a<0)
1
(True, False)
1
a<0
1
2
array([False, False, False, False, False, False, False, False, False,
       False])
  • Numpy 는 배열의 크기가 동일 할 때 element간 비교의 결과를 Boolean type으로 반환하여 돌려줌
1
2
3
test_a = np.array([1, 3, 0], float)
test_b = np.array([5, 2, 1], float)
test_a > test_b
1
array([False,  True, False])

np.where (중요!)

  • np.where(condition, TRUE, FALSE)
1
np.where(test_a > 0, 3, 2)
1
array([3, 3, 2])
1
np.where(a > 5)
1
(array([6, 7, 8, 9], dtype=int64),)
1
2
a = np.array([1,np.NaN, np.Inf], float)
np.isnan(a)
1
array([False,  True, False])
1
np.isfinite(a)
1
array([ True, False, False])

argmax & argmin (중요!)

  • 배열 내 최대값 또는 최소값의 index를 반환
  • axis 기반의 반환
  • axis = 0 : 행 방향 최대, 최소값의 index
  • axis = 1 : 열 방향 최대, 최소값의 index
1
2
a = np.array([1,2,4,5,8,78,23,3])
np.argmax(a), np.argmin(a)
1
(5, 0)
1
2
a = np.array([[1,2,4,7], [9,88,6,45],[9,76,3,4]])
np.argmax(a, axis=1), np.argmin(a, axis=0)
1
(array([3, 1, 1], dtype=int64), array([0, 0, 2, 2], dtype=int64))

6. numpy data i/o

loadtxt & savetxt

  • Text type의 데이터를 읽고, 저장하는 기능
1
2
a = np.loadtxt("./test.txt")
a
1
2
3
4
array([[ 1.,  2.,  3.,  4.],
       [ 5.,  6.,  7.,  8.],
       [ 9., 10., 11., 12.],
       [13., 14., 15., 16.]])
1
2
a_int = a.astype(int)
a_int
1
2
3
4
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])
1
np.savetxt('test.csv',a_int, fmt='%d', delimiter=",")

numpy object - npy

  • numpy object (pickle) 형태로 데이터를 저장하고 불러옴
  • binary 파일 형태로 저장함
1
np.save("npy_test.npy", arr=a_int)
1
2
npy_array = np.load(file="npy_test.npy")
npy_array
1
2
3
4
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12],
       [13, 14, 15, 16]])
This post is licensed under CC BY 4.0 by the author.

-

[Pandas 기초] 1. DataFrame 생성 및 불러오기