Numpy와 Pandas는 데이터 분석에 있어서 가장 기본이 되는 라이브러리입니다. Numpy는 수치 계산을 위한 라이브러리로, Pandas는 데이터 분석을 위한 라이브러리입니다. 이번 챕터에서는 Numpy 기본적인 사용법을 알아보겠습니다.
1. Numpy
Numpy는 C언어로 구현된 파이썬 라이브러리로, 행렬 연산이나 대규모 다차원 배열(ndarray)을 편리하게 처리할 수 있도록 지원합니다. NumPy는 데이터 구조 외에도 수치 계산을 위해 효율적으로 구현된 기능을 제공합니다. 데이터 분석을 할 때에도 Numpy를 사용하여 데이터를 처리하는 경우가 많아 뒤에서 배울 Pandas와 함께 필수로 알아야 하는 라이브러리입니다.
1.1 Numpy 배열 생성하기
Numpy 배열은 np.array()
함수를 사용하여 생성할 수 있습니다. 다음은 Numpy 배열을 생성하는 예제입니다.
import numpy as np
arr = np.array([1,2,3,4,5,6,7])
print(type(arr))
ndarray vs list
ndarray는 적은 메모리로 데이터를 빠르게 처리하고, 행렬의 곱셈 등 여러가지 선형대수 연산을 지원합니다. 반면 list는 속도가 매우 느리고, 원소가 각각 다른 자료형을 가질 수 있습니다.
1.2 Numpy 배열의 연산
Numpy 배열은 다양한 연산을 지원합니다.
import numpy as np
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([6, 7, 8, 9, 10])
print(arr1 + arr2)
# print(arr1 - arr2)
# print(arr1 * arr2)
# print(arr1 / arr2)
print(arr1 * 3) # 배열의 모든 원소에 3을 곱함
# print(np.dot(a, b)) # 행렬곱
# print(a @ b) # 행렬곱
1.3 배열의 인덱싱
Numpy 배열은 리스트와 같이 인덱싱을 지원합니다.
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr[0]) # 1
print(arr[1:3]) # [2, 3]
print(arr[-1]) # 7
1.4 차원
Numpy는 아래와 같은 차원을 지원합니다. ndim 속성을 사용하여 배열의 차원을 확인할 수 있습니다.
- 0차원: 스칼라, 숫자 하나, 점 하나
- 1차원: 벡터, 숫자들의 배열, 선
- 2차원: 행렬, 벡터들의 배열, 면
- 3차원 이상: 텐서, 행렬들의 배열, 공간
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.ndim) # 1
print(arr2.ndim) # 2
1.5 배열의 형태 변경
Numpy 배열의 형태를 변경할 수 있습니다. 형태를 변경할 때에는 차원을 추가할 수 있습니다.
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
print(arr.reshape(2, 3))
1.6 arange 함수
Numpy는 arange()
함수를 사용하여 배열을 생성할 수 있습니다. 파이썬의 range()
함수와 비슷하지만 arange()
함수는 소수점도 사용할 수 있습니다.
import numpy as np
arr = np.arange(1, 10, 0.5)
print(arr)
이를 활용해서 아래와 같은 형태로 변경도 가능합니다.
import numpy as np
arr = np.arange(1, 10, 0.5).reshape(6, 3)
print(arr)
arr2 = np.arange(40).reshape(2, 5, 4)
print(arr2)
1.7 배열의 슬라이싱
Numpy 배열은 리스트와 같이 슬라이싱을 지원합니다.
- 1차원:
arr[시작:끝:간격]
- 2차원:
arr[행시작:행끝, 열시작:열끝]
- 3차원:
arr[면, 행, 열]
과 같은 형태가 됩니다. [:, :, :]
로 표현할 수 있습니다.
import numpy as np
arr = np.arange(40).reshape(5, 8)
print(arr[1:3, 2:5])
print(arr[:, 2:5])
1.8 다양한 배열 만들기
Numpy는 다양한 배열을 만들 수 있는 함수를 제공합니다. 여기서는 가장 기본이 되는 함수들을 소개합니다.
np.zeros()
: 0으로 채워진 배열 생성
np.ones()
: 1로 채워진 배열 생성
import numpy as np
print(np.zeros((2, 3)))
print(np.ones((2, 3)))
1.9 집계 함수
Numpy는 다양한 집계 함수를 제공합니다. 여기서는 가장 기본이 되는 함수들을 소개합니다.
np.sum()
: 합계
np.mean()
: 평균
np.std()
: 표준편차
np.var()
: 분산
np.median()
: 중앙값
np.max()
: 최대값
np.min()
: 최소값
import numpy as np
arr = np.arange(40).reshape(5, 8)
print(np.sum(arr))
print(np.mean(arr))
print(np.std(arr))
1.10 불리언 인덱싱
Numpy 배열은 불리언 인덱싱을 지원합니다. 불리언 인덱싱은 조건을 만족하는 원소만 선택할 때 사용합니다.
import numpy as np
arr = np.arange(40).reshape(5, 8)
print(arr[arr > 20])
실제로 arr > 20은 다음과 같은 결과를 반환합니다.
이를 대입하여 불리언 인덱싱을 사용할 수 있습니다. 좀 더 쉬운 예제로 살펴보겠습니다.
import numpy as np
arr = np.array([1, 2, 3])
arr[[True, True, False]]
위와 같은 원리로 불리언 인덱싱이 동작하는 것입니다.
1.11 브로드캐스팅
브로드캐스팅은 크기가 다른 배열 간의 연산을 가능하게 해주는 기능입니다. Numpy는 자동으로 작은 배열을 큰 배열의 크기에 맞게 확장하여 연산을 수행합니다.
import numpy as np
# 스칼라와 배열의 연산
arr = np.array([1, 2, 3, 4, 5])
print(arr + 2) # 모든 원소에 2를 더함
print(arr * 3) # 모든 원소에 3을 곱함
이번에는 1차원 배열과 2차원 배열의 연산을 살펴보겠습니다.
# 1차원 배열과 2차원 배열의 연산
arr1 = np.array([1, 2, 3])
arr2 = np.array([[4, 5, 6],
[7, 8, 9]])
print("\n1차원과 2차원 배열의 덧셈:")
print(arr1 + arr2) # arr1이 자동으로 arr2의 형태에 맞춰짐
브로드캐스팅의 규칙
- 작은 배열이 큰 배열의 shape와 호환되어야 합니다.
- 두 배열의 차원이 다를 경우, 작은 차원의 배열이 큰 차원의 배열에 맞춰집니다.
1.12 배열의 정렬과 탐색
Numpy는 배열을 정렬하고 특정 값을 찾는 다양한 함수를 제공합니다.
import numpy as np
# 1차원 배열 정렬
arr = np.array([3, 1, 4, 1, 5, 9, 2, 6])
print("원본 배열:", arr)
print("정렬된 배열:", np.sort(arr)) # 원본 배열은 변경되지 않음
# 2차원 배열 정렬
arr_2d = np.array([[3, 1, 4],
[1, 5, 9],
[2, 6, 5]])
print("\n2차원 배열:")
print(arr_2d)
print("\n각 행을 정렬한 결과:")
print(np.sort(arr_2d, axis=1)) # axis=1은 행 방향 정렬, axis=0은 열 방향 정렬
이번에는 값이 있는 위치를 찾는 방법을 살펴보겠습니다. where() 함수를 사용하여 값을 찾을 수 있습니다. 이 함수는 차원에 관련없이 사용할 수 있습니다.
# 값 찾기
arr = np.array([10, 20, 30, 40, 50])
index = np.where(arr == 30) # 값 30의 인덱스 찾기
print("30의 위치:", index[0][0])
1.13 배열의 결합과 분할
여러 개의 배열을 하나로 합치거나 하나의 배열을 여러 개로 나눌 수 있습니다.
import numpy as np
# 배열 결합하기
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
# 가로로 결합
horizontal = np.hstack((arr1, arr2))
print("가로로 결합:", horizontal)
# 세로로 결합
vertical = np.vstack((arr1, arr2))
print("\n세로로 결합:")
print(vertical)
이번에는 배열을 분할하는 방법을 살펴보겠습니다.
# 배열 분할하기
arr = np.array([1, 2, 3, 4, 5, 6])
print("원본 배열:", arr)
# 배열을 3등분
split_arr = np.array_split(arr, 3)
print("3등분 결과:")
for piece in split_arr:
print(piece)
결합 함수의 종류
- hstack(): 가로 방향으로 배열을 결합
- vstack(): 세로 방향으로 배열을 결합
- concatenate(): axis 매개변수로 방향을 지정하여 결합
1.14 랜덤 함수
Numpy는 다양한 랜덤 함수를 제공합니다. 여기서는 가장 기본이 되는 함수들을 소개합니다.
- seed : 시작 숫자를 정해 정해진 난수 알고리즘으로 난수 생성
- shuffle : 데이터의 순서를 바꿔줌
- choice : 데이터에서 일부를 무작위로 선택
- rand : 0부터 1까지 균일 분포로 난수 생성
- randn : 가우시안 표준 정규 분포로 난수 생성
import random as r
print(r.randint(1, 10)) # 1부터 10까지의 임의의 정수를 리턴
print(r.random()) # 0부터 1까지의 부동소수점 숫자를 리턴
print(r.uniform(1, 10)) # 1부터 10까지의 부동소수점 숫자를 리턴
print(r.randrange(1, 10, 2)) # 1부터 9까지 2 간격으로 임의의 정수를 리턴