파이썬 기초: 라이브러리-Numpy
본 페이지에서는 코드의 실행결과를 제공하지 않습니다. 직접 타이핑하고 실행해 보세요.
1. Numpy 개요
1-1. Numpy란?
- NumPy : Numerical Python
- 고성능의 과학계산 컴퓨팅과 데이터 분석에 필요한 기본패키지
- 행렬이나 대규모의 다차원 배열을 쉽게 처리
- 계산과학(Computational Science) 분야의 복잡한 연산을 지원
- SciPy, Matplotlib, Pandas 등에 채용되어 더 복잡한 연산을 쉽게 처리 가능하도록 지원
1-2. NumPy에서 제공하는 기능
- ndarray 지원: 빠르고 메모리를 효율적으로 사용하며, 벡터 산술연산과 세련된 브로드캐스팅 기능을 제공하는 다차원 배열
- 반복문을 작성할 필요 없이 전체 데이터 배열에 대해 빠른 연산을 제공하는 표준 수학 함수
- 배열 데이터를 디스크에 쓰거나 읽을 수 있는 도구와 메모리에 올려진 파일을 사용하는 도구
- 선형대수, 난수 발생기, 푸리에 변환 기능
- C, C++, 포트란으로 쓰여진 코드를 통합하는 도구
- 사용하기 편한 C API제공
- 데이터를 다른 저수준 언어로 쓰여진 외부 라이브러리에 쉽게 전달할 수 있도록 지원
- 외부 라이브러리에서 반환된 데이터를 파이썬의 NumPy 배열 형태로 불러올 수 있도록 지원
- 파이썬을 레거시 C/C++/포트란 기반의 코드를 래핑하여 동적이며 쉽게 사용할 수 있는 인터페이스를 만들 수 있는 언어로 만들어 줌
1-3. Numpy를 잘 활용하려면
- NumPy는 자체적으로는 고수준의 데이터 분석 기능을 제공하지 않으므로
- 먼저 NumPy 배열과 배열기반의 컴퓨팅에 대한 이해가 선행된다면
- 더 상위 레벨에서 데이터 분석과 같은 기능을 제공하는 Pandas 등의 도구들을 더욱 효율적으로 사용할 수 있음
1-4. 대부분의 데이터 분석 애플리케이션에서 중요하게 사용되는 기능
- 벡터배열 상에서 데이터 개조, 정제, 부분집합, 필터링, 변형, 이종연산의 빠른 수행
- 정렬, 유일 원소 찾기, 집합연산과 같은 일반적인 배열 처리 알고리즘
- 통계의 효과적인 표현과 데이터의 수집/요약
- 이종의 데이터 묶음을 병합하고 엮기 위한 데이터 정렬과 데이터 간의 관계 조작
- if ~ elif ~ else 포함 반복문 대신 사용가능한 조건절 표현을 할 수 있는 배열 표현
- 데이터 그룹 전체에 적용할 수 있는 수집, 변형, 함수의 적용과 같은 데이터 처리
2. Numpy 실습 예제
2-1. ndarray (n-Dimension Array)
numpy import
import numpy as np
- ndarray 배열은 산술 연산이 가능함
- ndarray 배열은 각 차원의 크기를 알려주는 shape라는 튜플을 가짐
ndarray 배열은 배열에 저장된 자료형을 알려주는 dtype이라는 객체를 가짐
data = np.random.randn(2, 3) print(data)
data
print(data * 10) print(data + data)
print(data.shape) print(data.dtype)
ndarray의 생성과 사용
data1 = [6, 7.5, 8, 0, 1] arr1 = np.array(data1) arr1
print(arr1.ndim) print(data1)
같은 길이의 리스트가 담겨있는 순차 데이터는 다차원 배열로 변환이 가능함
data2 = [[1, 2, 3, 4], [5, 6, 7, 8]] arr2 = np.array(data2) arr2
print(arr2.ndim) print(arr2.shape)
명시적으로 지정하지 않는 한 np.array는 생성될 때 적절한 자료형을 지정하여 적용함
print(arr1.dtype) print(arr2.dtype)
새로운 배열을 생성하기 위한 다양한 함수 보유
np.zeros(10) # 10개의 요소가 0으로 채워진 1차원 배열 생성
np.zeros((3, 6)) # 6개의 요소를 가진 1차원 배열이 3개가 포함된 2차원 배열 생성
np.empty((2, 3, 2)) # empty 함수는 초기화되지 않은 배열 생성. 원하는 형태를 정의한 튜플을 넘기면 해당 형태로 생성
파이썬의 range 함수의 배열 버전인 arange 함수
np.arange(15)
range(15)
데이터 타입 확인
arr0 = np.array([1., 2, 3]) arr1 = np.array([1, 2, 3], dtype=np.float64) arr2 = np.array([1, 2, 3], dtype=np.int32) print(arr0.dtype) print(arr0) print(arr1.dtype) print(arr1) print(arr2.dtype) print(arr2)
arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1]) arr1 = arr.astype(np.int32) print(arr1)
import copy arr2 = arr1 arr2[0] = 10 print(arr2) print(arr1)
arr3 = copy.copy(arr1) arr3[0] = 20 print(arr3) print(arr1)
numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_) print(numeric_strings) numeric_strings.astype(float)
int_array = np.arange(10) print(int_array.dtype) calibers = np.array([.22, .270, .357, .380, .44, .50], dtype=np.float64) print(calibers.dtype) int_array.astype(calibers.dtype)
empty_uint32 = np.empty(8, dtype='u4') empty_uint32
산술 연산
arr = np.array([[1., 2., 3.], [4., 5., 6.]]) arr
print(arr + arr) print(arr - arr) print(arr * arr) print(1 / arr) print(arr ** 0.5)
arr2 = np.array([[0., 4., 1.], [7., 2., 12.]]) arr2
arr2 > arr
2-2. 인덱싱과 슬라이싱
기본 인덱싱
arr = np.arange(10) arr
arr[5]
arr[5:8]
arr[5:8] = 12
arr
arr_slice = arr[5:8] arr_slice
arr_slice[1] = 12345 arr
arr_slice[:] = 64 arr
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) arr2d[2]
arr2d[0][2]
arr2d[0, 2]
arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) arr3d
arr3d[0]
old_values = arr3d[0].copy() arr3d[0] = 42 arr3d
arr3d[0] = old_values arr3d
arr3d[1, 0]
x = arr3d[1] x x[0]
슬라이스를 이용한 인덱싱
arr
arr[1:6]
arr2d
arr2d[:2]
arr2d[:2, 1:]
arr2d[1, :2]
arr2d[:2, 2]
arr2d[:, :1]
arr2d[:2, 1:] = 0 arr2d
불린 인덱싱
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe']) data = np.random.randn(7, 4)
names
data
names == 'Bob'
data[names == 'Bob']
data[names == 'Bob', 2:]
data[names == 'Bob', 3]
names != 'Bob'
data[(names != 'Bob')]
data[~(names == 'Bob')]
cond = names == 'Bob' data[~cond]
mask = (names == 'Bob') | (names == 'Will') print(mask) data[mask]
data[data < 0] = 0 data
data[names != 'Joe'] = 7 data
팬시 인덱싱
arr = np.empty((8, 4)) arr
for i in range(8): arr[i] = i arr
arr[[4, 3, 0, 6]]
arr[[-3, -5, -7]]
arr = np.arange(32) arr
arr = arr.reshape((8, 4)) arr
arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]
2-3. 전치행렬과 축 교환
arr = np.arange(15).reshape((3, 5))
arr
arr.T
arr = np.random.randn(6, 3)
arr
np.dot(arr.T, arr)
arr = np.arange(16).reshape((2, 2, 4))
arr
arr.transpose((1, 0, 2))
arr
arr.swapaxes(1, 2)
2-4. 유니버설 함수
ndarray 안에 있는 데이터 원소별로 연산을 수행하는 함수
arr = np.arange(10) arr
np.sqrt(arr)
np.exp(arr)
x = np.random.randn(8) y = np.random.randn(8) x y np.maximum(x, y)
arr = np.random.randn(7) * 5 print(arr)
remainder, whole_part = np.modf(arr) print(remainder) print(whole_part)
arr np.sqrt(arr) np.sqrt(arr, arr) arr
2-5. 배열을 사용한 데이터 처리
points = np.arange(-5, 5, 0.01) # 1000 equally spaced points
xs, ys = np.meshgrid(points, points)
ys
z = np.sqrt(xs 2 + ys 2)
z
import matplotlib.pyplot as plt
plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()
plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")
plt.draw()
plt.close('all')
2-5-1. 배열연산으로 조건절 표현하기
xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
cond = np.array([True, False, True, True, False])
result = [(x if c else y)
for x, y, c in zip(xarr, yarr, cond)]
result
result = np.where(cond, xarr, yarr)
result
arr = np.random.randn(4, 4)
arr
arr > 0
np.where(arr > 0, 2, -2)
np.where(arr > 0, 2, arr) # set only positive values to 2
2-5-2. 수학 메소드와 통계 메소드
arr = np.random.randn(5, 4)
arr
arr.mean()
np.mean(arr)
arr.sum()
arr.mean(axis=1)
arr.sum(axis=0)
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])
arr.cumsum()
arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
arr
print(arr.cumsum(axis=0))
print(arr.cumprod(axis=1))
2-5-3. 불리언 배열을 위한 메소드
arr = np.random.randn(100)
(arr > 0).sum() # Number of positive values
arr
print(arr>0)
bools = np.array([False, False, True, False])
bools.any()
bools.all()
2-5-4. 정렬
arr = np.random.randn(6)
arr
arr.sort()
arr
arr = np.random.randn(5, 3)
arr
arr.sort(1)
arr
large_arr = np.random.randn(100)
print(large_arr)
large_arr.sort()
print(large_arr)
large_arr[int(0.5 * len(large_arr))]
2-5-5. 집합함수
names = np.array(['Joe', 'Will', 'Bob', 'Will', 'Bob', 'Joe', 'Joe'])
np.unique(names)
ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])
np.unique(ints)
# sorted(set(names))
set(names)
values = np.array([6, 0, 0, 3, 2, 5, 6])
np.in1d(values, [2, 3, 6])
2-5-6. 배열을 사용한 파일 입출력
arr = np.arange(10)
np.save('./some_array.txt', arr)
np.load('./some_array.txt.npy')
np.savez('./array_archive.npz', a=arr, b=arr)
arch = np.load('./array_archive.npz')
print(arch['b'])
print(arch['a'])
np.savez_compressed('./arrays_compressed.npz', a=arr, b=arr)
pwd
rm some_array.txt.npy
rm array_archive.npz
rm arrays_compressed.npz
2-6. 선형대수
x = np.array([[1., 2., 3.], [4., 5., 6.]])
y = np.array([[6., 23.], [-1, 7], [8, 9]])
x
y
x.dot(y)
np.dot(x, y)
np.ones(3)
np.dot(x, np.ones(3))
np.ones(3)
x @ np.ones(3)
from numpy.linalg import inv, qr
X = np.random.randn(5, 5)
mat = X.T.dot(X)
inv(mat)
mat.dot(inv(mat))
q, r = qr(mat)
r
2-7. 난수 생성
samples = np.random.normal(size=(4, 4))
samples
from random import normalvariate
N = 10000
%timeit samples = [normalvariate(0, 1) for _ in range(N)]
%timeit np.random.normal(size=N)
np.random.seed(1234)
rng = np.random.RandomState(1234)
rng.randn(10)