Python - Numpy 기초 예제
4. NumPy Basics: Arrays and Vectorized Computation
import numpy as np
np.random.seed(12345)
import matplotlib.pyplot as plt
plt.rc('figure', figsize=(10, 6))
np.set_printoptions(precision=4, suppress=True)
import numpy as np
my_arr = np.arange(1000000)
my_list = list(range(1000000))
%time for _ in range(10): my_arr2 = my_arr * 2
%time for _ in range(10): my_list2 = [x * 2 for x in my_list]
Wall time: 25.9 ms
Wall time: 1.36 s
4.1 The NumPy ndarray: A Multidimensional Array Object
import numpy as np
# Generate some random data
data = np.random.randn(2, 3)
data
array([[-0.2047, 0.4789, -0.5194],
[-0.5557, 1.9658, 1.3934]])
data * 10
array([[-2.0471, 4.7894, -5.1944],
[-5.5573, 19.6578, 13.9341]])
data + data
array([[-0.4094, 0.9579, -1.0389],
[-1.1115, 3.9316, 2.7868]])
print(data.shape); print(data.dtype)
(2, 3)
float64
4.4.1 Creating ndarrays
data1 = [6, 7.5, 8, 0, 1]
arr1 = np.array(data1)
arr1
array([6. , 7.5, 8. , 0. , 1. ])
data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
arr2 = np.array(data2)
arr2
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
print(arr2.ndim); print(arr2.shape)
2
(2, 4)
print(arr1.dtype); print(arr2.dtype)
float64
int32
# 초기값을 가진 배열 생성하기 :
np.zeros(10)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
np.ones((3, 6))
array([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]])
np.empty((2, 3, 2))
array([[[1.1250e-311, 2.8162e-322],
[0.0000e+000, 0.0000e+000],
[0.0000e+000, 2.4234e-057]],
[[5.9523e-091, 8.6952e-071],
[4.3187e-038, 2.9564e-032],
[6.4822e+170, 4.9343e+257]]])
np.arange(15)
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
4.1.2 Data Types for ndarrays
# dtype 옵션 :
arr1 = np.array([1, 2, 3], dtype=np.float64)
arr2 = np.array([1, 2, 3], dtype=np.int32)
print(arr1); print(arr2)
[1. 2. 3.]
[1 2 3]
# astype() 메소드 :
arr = np.array([1, 2, 3, 4, 5])
float_arr = arr.astype(np.float64)
print(arr.dtype); print(float_arr.dtype)
int32
float64
# astype() 메소드 :
# 소수점 아래 자리는 버린다.
arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
print(arr)
print(arr.astype(np.int32))
[ 3.7 -1.2 -2.6 0.5 12.9 10.1]
[ 3 -1 -2 0 12 10]
numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)
numeric_strings.astype(float)
array([ 1.25, -9.6 , 42. ])
# astype() 메소드 :
# 다른 배열의 type을 사용하여 데이터 형 변환.
int_array = np.arange(10)
calibers = np.array([.22, .270, .357, .380, .44, .50], dtype=np.float64)
int_array.astype(calibers.dtype)
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
# u4 : unit32와 동일하다.
empty_uint32 = np.empty(8, dtype='u4')
empty_uint32
array([ 595210624, 530, 1, 1044258848, 595210056,
530, 595210048, 530], dtype=uint32)
4.1.3 Arithmetic with NumPy Arrays
# 벡터화 :
# 같은 크기의 배열은 배열의 원소 단위로 수행된다.
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
print(arr)
print(arr * arr)
print(arr - arr)
[[1. 2. 3.]
[4. 5. 6.]]
[[ 1. 4. 9.]
[16. 25. 36.]]
[[0. 0. 0.]
[0. 0. 0.]]
# 벡터와 스칼라
print(1 / arr)
print(arr ** 0.5)
[[1. 0.5 0.3333]
[0.25 0.2 0.1667]]
[[1. 1.4142 1.7321]
[2. 2.2361 2.4495]]
arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
arr2
arr2 > arr
array([[False, True, False],
[ True, False, True]])
4.1.4 Basic Indexing and Slicing
# 인덱싱 :
# 브로드캐스팅
# 배열 = 스칼라 ?
arr = np.arange(10)
print(arr)
print(arr[5])
print(arr[5:8])
arr[5:8] = 12
print(arr)
[0 1 2 3 4 5 6 7 8 9]
5
[5 6 7]
[ 0 1 2 3 4 12 12 12 8 9]
# 배열 조삭(slicing) : memory model
# 원본 배열의 views이다. :
# 데이터는 복사되지 않고, 뷰에 대한 변경은
# 그대로 원본배열에 반영된다는 것이다.
# 리스트와 중요한 차이점이다.
arr_slice = arr[5:8]
arr_slice
array([12, 12, 12])
arr_slice[1] = 12345
arr
array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8,
9])
arr_slice[:] = 64
arr
array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])
# 다차원 배열 : 2차원 배열
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2d[2]
array([7, 8, 9])
print(arr2d[0][2]) # 재귀적 표현
print(arr2d[0, 2]) # 간단한 표현
3
3
# 다차원 배열 : 3차원 배열
arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
arr3d
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
arr3d[0]
array([[1, 2, 3],
[4, 5, 6]])
# 3차원 배열에 대입문
# 1) scalar, 2) 배열
old_values = arr3d[0].copy()
arr3d[0] = 42
print(arr3d)
arr3d[0] = old_values
print(arr3d)
[[[42 42 42]
[42 42 42]]
[[ 7 8 9]
[10 11 12]]]
[[[ 1 2 3]
[ 4 5 6]]
[[ 7 8 9]
[10 11 12]]]
arr3d[1, 0]
array([7, 8, 9])
# 변수
x = arr3d[1]
print(x)
print(x[0])
print(x.shape)
[[ 7 8 9]
[10 11 12]]
[7 8 9]
(2, 3)
Indexing with slices
# list와 같은 1차원 객체처럼 slice할 수 있다.
print(arr)
print(arr[1:6])
[ 0 1 2 3 4 64 64 64 8 9]
[ 1 2 3 4 64]
# 축을 기준으로 slicing할 수 있다.
# 첫번째 축인 0번 축을 기준으로
print(arr2d)
print(arr2d[:2])
[[1 2 3]
[4 5 6]
[7 8 9]]
[[1 2 3]
[4 5 6]]
# 다차원 slicing :
# 축을 따라 선택 영역내의 원소가 선택된다.
arr2d[:2, 1:]
array([[2, 3],
[5, 6]])
# 정수 색인과 슬라이스틀 함께 사용하면,
# 한 차원 낮은 슬라이스를 얻을 수 있다.
arr2d[1, :2]
array([4, 5])
x=arr2d[:2, 2]
print(x.shape)
print(x)
(2,)
[3 6]
# 이렇게 하면 원래 차원의 슬라이스를 얻을 수 있다.
arr2d[:, :1]
array([[1],
[4],
[7]])
# 슬라이싱 구문에 값을 대입하면
# 선택 영역 전체에 값이 할당된다.
arr2d[:2, 1:] = 0
arr2d
array([[1, 0, 0],
[4, 0, 0],
[7, 8, 9]])
4.1.5 Boolean Indexing
# 실험 데이터 준비
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
data = np.random.randn(7, 4)
print(names)
print(data)
['Bob' 'Joe' 'Will' 'Bob' 'Will' 'Joe' 'Joe']
[[ 0.0929 0.2817 0.769 1.2464]
[ 1.0072 -1.2962 0.275 0.2289]
[ 1.3529 0.8864 -2.0016 -0.3718]
[ 1.669 -0.4386 -0.5397 0.477 ]
[ 3.2489 -1.0212 -0.5771 0.1241]
[ 0.3026 0.5238 0.0009 1.3438]
[-0.7135 -0.8312 -2.3702 -1.8608]]
# 배열에 대한 연산자 :
# 이것도 벡터화된다.
names == 'Bob'
array([ True, False, False, True, False, False, False])
# 불리언 배열을 색인으로 사용 :
# 불리언 배열은 반드시 색인하려는 축의 길이와 동일한
# 길이이어야 한다.
data[names == 'Bob']
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.669 , -0.4386, -0.5397, 0.477 ]])
print(data[names == 'Bob', 2:])
print(data[names == 'Bob', 3])
[[ 0.769 1.2464]
[-0.5397 0.477 ]]
[1.2464 0.477 ]
print(names != 'Bob')
print(data[~(names == 'Bob')])
[False True True False True True True]
[[ 1.0072 -1.2962 0.275 0.2289]
[ 1.3529 0.8864 -2.0016 -0.3718]
[ 3.2489 -1.0212 -0.5771 0.1241]
[ 0.3026 0.5238 0.0009 1.3438]
[-0.7135 -0.8312 -2.3702 -1.8608]]
cond = names == 'Bob'
print(data[~cond])
[[ 1.0072 -1.2962 0.275 0.2289]
[ 1.3529 0.8864 -2.0016 -0.3718]
[ 3.2489 -1.0212 -0.5771 0.1241]
[ 0.3026 0.5238 0.0009 1.3438]
[-0.7135 -0.8312 -2.3702 -1.8608]]
# 3가지 이름 중에서 2 가지 이름을 선택하려면,
# &(and 와 |(or같은 논리 연산자를 사용하면 된다.
# keyword 'and', 'or'는 불리언 배열에 사용 못한다..
mask = (names == 'Bob') | (names == 'Will')
print(mask)
print(data[mask])
[ True False True True True False False]
[[ 0.0929 0.2817 0.769 1.2464]
[ 1.3529 0.8864 -2.0016 -0.3718]
[ 1.669 -0.4386 -0.5397 0.477 ]
[ 3.2489 -1.0212 -0.5771 0.1241]]
# 불리언 색인을 사용해서 배열을 선택하면,
# 항상 데이터 복사가 일어난다.
# 배열의 내용이 바뀌지 않더라도
# 불리언 배열로 값을 설정할 때는 상식적으로 동작한다.
data[data < 0] = 0
data
array([[0.0929, 0.2817, 0.769 , 1.2464],
[1.0072, 0. , 0.275 , 0.2289],
[1.3529, 0.8864, 0. , 0. ],
[1.669 , 0. , 0. , 0.477 ],
[3.2489, 0. , 0. , 0.1241],
[0.3026, 0.5238, 0.0009, 1.3438],
[0. , 0. , 0. , 0. ]])
# 1차원 불리언 배열로 전행 행이나 열을 선택하는 것도 쉽다.
data[names != 'Joe'] = 7
data
array([[7. , 7. , 7. , 7. ],
[1.0072, 0. , 0.275 , 0.2289],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[0.3026, 0.5238, 0.0009, 1.3438],
[0. , 0. , 0. , 0. ]])
4.1.6 Fancy Indexing
# 정수 배열을 사용한 색인
arr = np.empty((8, 4))
for i in range(8):
arr[i] = i
arr
array([[0., 0., 0., 0.],
[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.],
[4., 4., 4., 4.],
[5., 5., 5., 5.],
[6., 6., 6., 6.],
[7., 7., 7., 7.]])
# 특정한 순서로 행을 선택하고자 할 경우,
# 정수 값을 가진 ndarray나 list로 지정.
arr[[4, 3, 0, 6]]
array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
arr[[-3, -5, -7]]
array([[5., 5., 5., 5.],
[3., 3., 3., 3.],
[1., 1., 1., 1.]])
# 다차원 색인 배열인 경우에,
# 각각의 색인 튜플에 대응하는 1차원 배열이 생성
arr = np.arange(32).reshape((8, 4))
print(arr)
print(arr[[1, 5, 7, 2], [0, 3, 1, 2]])
[[ 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]]
[ 4 23 29 10]
# 행렬의 행과 열에 대응하는 사각형 모양의 값을
# 출력하기 위해서
arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
# 팬시 색인은 슬라이싱과 달리 선택된 데이터를 새로운
# 배열로 복사한다.
4.1.7 Transposing Arrays and Swapping Axes
# 배열 전치는 데이터를 복사하지 않고
# 데이터 모양이 바뀐 뷰를 반환하는 특별한 기능이다.
# transpose() 메서드와 T 속성
arr = np.arange(15).reshape((3, 5))
print(arr)
print(arr.T)
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
[[ 0 5 10]
[ 1 6 11]
[ 2 7 12]
[ 3 8 13]
[ 4 9 14]]
# 행렬의 내적 : np.dot() 메서드
arr = np.random.randn(6, 3)
print(arr)
print(np.dot(arr.T, arr))
[[ 0.585 0.1527 -1.5657]
[-0.5625 -0.0327 -0.929 ]
[-0.4826 -0.0363 1.0954]
[ 0.9809 -0.5895 1.5817]
[-0.5287 0.457 0.93 ]
[-1.5693 -1.0225 -0.4028]]
[[ 4.5959 0.9099 0.7701]
[ 0.9099 1.6275 -0.3439]
[ 0.7701 -0.3439 8.0431]]
arr = np.arange(16).reshape((2, 2, 4))
print(arr)
print(arr.transpose((1, 0, 2)))
[[[ 0 1 2 3]
[ 4 5 6 7]]
[[ 8 9 10 11]
[12 13 14 15]]]
[[[ 0 1 2 3]
[ 8 9 10 11]]
[[ 4 5 6 7]
[12 13 14 15]]]
arr
arr.swapaxes(1, 2)
array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]],
[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])
4.2 Universal Functions: Fast Element-Wise Array Functions
# ndarray 안에 있는데이터 원소별로 연산을
# 수행하는 함수이다.
arr = np.arange(10)
arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 단항 유니버설 함수
print(np.sqrt(arr))
print(np.exp(arr))
[0. 1. 1.4142 1.7321 2. 2.2361 2.4495 2.6458 2.8284 3. ]
[ 1. 2.7183 7.3891 20.0855 54.5982 148.4132 403.4288
1096.6332 2980.958 8103.0839]
# 다항 유니버설 함수
x = np.random.randn(8)
y = np.random.randn(8)
print(x)
print(y)
print(np.maximum(x, y))
[ 0.2205 -0.1934 0.6692 -1.649 -2.2528 -1.1668 0.3536 0.7021]
[-0.2746 -0.1391 0.1077 -0.6065 -0.4171 -0.017 -1.2241 -1.8008]
[ 0.2205 -0.1391 0.6692 -0.6065 -0.4171 -0.017 0.3536 0.7021]
# 배열 여러개를 반환하는 함수
# 흔하지 않은 경우.
arr = np.random.randn(7) * 5
arr
array([ 2.494 , -4.12 , 6.6028, 2.5398, -3.2672, 0.9349, -1.9586])
remainder, whole_part = np.modf(arr)
print(remainder)
print(whole_part)
[ 0.494 -0.12 0.6028 0.5398 -0.2672 0.9349 -0.9586]
[ 2. -4. 6. 2. -3. 0. -1.]
print(arr)
np.sqrt(arr)
np.sqrt(arr, arr)
print(arr)
[ 2.494 -4.12 6.6028 2.5398 -3.2672 0.9349 -1.9586]
[1.5792 nan 2.5696 1.5937 nan 0.9669 nan]
C:\DTools\Anaconda3\envs\tf\lib\site-packages\ipykernel_launcher.py:2: RuntimeWarning: invalid value encountered in sqrt
C:\DTools\Anaconda3\envs\tf\lib\site-packages\ipykernel_launcher.py:3: RuntimeWarning: invalid value encountered in sqrt
This is separate from the ipykernel package so we can avoid doing imports until
4.3 Array-Oriented Programming with Arrays
# 벡터화 :
# 배열 연산을 사용해서 반복문을 명시적으로 제거하는 기법
points = np.arange(-5, 5, 0.01) # 1000 equally spaced points
xs, ys = np.meshgrid(points, points)
ys
array([[-5. , -5. , -5. , ..., -5. , -5. , -5. ],
[-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],
[-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],
...,
[ 4.97, 4.97, 4.97, ..., 4.97, 4.97, 4.97],
[ 4.98, 4.98, 4.98, ..., 4.98, 4.98, 4.98],
[ 4.99, 4.99, 4.99, ..., 4.99, 4.99, 4.99]])
z = np.sqrt(xs ** 2 + ys ** 2)
z
array([[7.0711, 7.064 , 7.0569, ..., 7.0499, 7.0569, 7.064 ],
[7.064 , 7.0569, 7.0499, ..., 7.0428, 7.0499, 7.0569],
[7.0569, 7.0499, 7.0428, ..., 7.0357, 7.0428, 7.0499],
...,
[7.0499, 7.0428, 7.0357, ..., 7.0286, 7.0357, 7.0428],
[7.0569, 7.0499, 7.0428, ..., 7.0357, 7.0428, 7.0499],
[7.064 , 7.0569, 7.0499, ..., 7.0428, 7.0499, 7.0569]])
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")
Text(0.5, 1.0, 'Image plot of $\\sqrt{x^2 + y^2}$ for a grid of values')
plt.draw()
<Figure size 720x432 with 0 Axes>
plt.close('all')
4.3.1 Expressing Conditional Logic as Array Operations
# np.where 함수 : 벡터화
# 'x if 조건 else y'와 같은 3항식 벡터와 버전
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
[1.1, 2.2, 1.3, 1.4, 2.5]
result = np.where(cond, xarr, yarr)
result
array([1.1, 2.2, 1.3, 1.4, 2.5])
arr = np.random.randn(4, 4)
print(arr)
print(arr > 0)
[[-0.2723 -0.0171 0.6803 0.6355]
[-0.7572 0.7181 -0.3043 -1.6778]
[ 0.427 -1.5637 -0.3675 1.0459]
[ 1.22 -0.2477 -0.4162 -0.1167]]
[[False False True True]
[False True False False]
[ True False False True]
[ True False False False]]
np.where(arr > 0, 2, -2)
array([[-2, -2, 2, 2],
[-2, 2, -2, -2],
[ 2, -2, -2, 2],
[ 2, -2, -2, -2]])
np.where(arr > 0, 2, arr) # set only positive values to 2
array([[-0.2723, -0.0171, 2. , 2. ],
[-0.7572, 2. , -0.3043, -1.6778],
[ 2. , -1.5637, -0.3675, 2. ],
[ 2. , -0.2477, -0.4162, -0.1167]])
4.3.2 Mathematical and Statistical Methods
arr = np.random.randn(5, 4)
arr
array([[-1.8448, 2.0687, -0.777 , 1.4402],
[-0.1106, 1.2274, 1.9208, 0.7464],
[ 2.2247, -0.6794, 0.7274, -0.8687],
[-1.2139, -0.4706, -0.9192, -0.8388],
[ 0.4352, -0.5578, -0.5675, -0.3726]])
# 전체
print(arr.mean())
print(np.mean(arr))
print(arr.sum())
0.0784883866913893
0.0784883866913893
1.569767733827786
# mean()이나 sum() 같은 함수는 옵션으로 해당 axis 인수를
# 받아 축에 대한 통계를 계산하고 한 차원 낮은 배열을
# 반환한다.
print(arr.mean(axis=1))
print(arr.sum(axis=0))
[ 0.2218 0.946 0.351 -0.8606 -0.2657]
[-0.5094 1.5883 0.3845 0.1064]
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])
arr.cumsum()
array([ 0, 1, 3, 6, 10, 15, 21, 28], dtype=int32)
arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
arr
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
print(arr.cumsum(axis=0))
print(arr.cumprod(axis=1))
[[ 0 1 2]
[ 3 5 7]
[ 9 12 15]]
[[ 0 0 0]
[ 3 12 60]
[ 6 42 336]]
4.3.3 Methods for Boolean Arrays
arr = np.random.randn(100)
arr
array([-0.9266, 1.7551, 1.2098, 1.27 , -0.9744, -0.6347, -0.3957,
-0.2894, -0.7343, -0.7285, 0.8388, 0.2669, 0.7212, 0.911 ,
-1.0209, -1.4134, 1.2966, 0.2523, 1.1275, -0.5684, 0.3094,
-0.5774, -1.1686, -0.825 , -2.6444, -0.153 , -0.7519, -0.1326,
1.4573, 0.6095, -0.4938, 1.24 , -0.1357, 1.43 , -0.8469,
0.6033, 1.2636, -0.2555, -0.4457, 0.4684, -0.9616, -1.8245,
0.6254, 1.0229, 1.1074, 0.0909, -0.3501, 0.218 , -0.8948,
-1.7415, -1.0523, 1.4366, -0.5762, -2.4203, -1.0623, 0.2374,
0.001 , 0.0653, -1.3675, -0.0303, 0.9405, -0.6424, 1.0402,
-1.0829, 0.4292, -0.2362, 0.6418, -0.3317, 1.3941, -1.0767,
-0.1925, -0.8712, 0.4209, -1.2114, -0.2589, -0.5816, -1.2604,
0.4646, -1.0702, 0.8042, -0.1567, 2.0104, -0.8871, -0.9779,
-0.2672, 0.4833, -0.4003, 0.4499, 0.3996, -0.1516, -2.5579,
0.1608, 0.0765, -0.2972, -1.2943, -0.8852, -0.1875, -0.4936,
-0.1154, -0.3507])
(arr > 0).sum() # Number of positive values
41
# any() 메서드 :
# 하나 이상의 True 값이 있는 지를 검사하고,
# all() 메서드 :
# 모든 원소가 True인지 검사한다.
bools = np.array([False, False, True, False])
print(bools.any())
print(bools.all())
True
False
4.3.4 Sorting
# sort() 메서드 :
# in-place 정렬을 한다.
arr = np.random.randn(6)
arr
array([ 0.0447, -0.8978, 0.8909, -1.1512, -2.6123, 1.1413])
arr.sort()
arr
array([-2.6123, -1.1512, -0.8978, 0.0447, 0.8909, 1.1413])
# 다차원 배열의 경우 :
# 지정된 축의 값의 따라 1차원 부분을 정렬한다.
arr = np.random.randn(5, 3)
arr
array([[-0.8671, 0.3836, -0.437 ],
[ 0.3475, -1.2302, 0.5711],
[ 0.0601, -0.2255, 1.3497],
[ 1.3503, -0.3867, 0.866 ],
[ 1.7472, -1.4102, -0.3782]])
arr.sort(1)
arr
array([[-0.8671, -0.437 , 0.3836],
[-1.2302, 0.3475, 0.5711],
[-0.2255, 0.0601, 1.3497],
[-0.3867, 0.866 , 1.3503],
[-1.4102, -0.3782, 1.7472]])
large_arr = np.random.randn(1000)
large_arr.sort()
large_arr[int(0.05 * len(large_arr))] # 5% quantile
4.3.5 Unique and Other Set Logic
# 집합 연산 :
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
np.unique(names)
ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])
np.unique(ints)
array([1, 2, 3, 4])
sorted(set(names))
['Bob', 'Joe', 'Will']
# in1d() 메서드 :
# 2개의 배열을 인수로 받아서 첫번째 배열의 각 원소가
# 두번째 배열의 원소를 포함하는 지를 나타내는
# 불리언 배열을 반환한다.
values = np.array([6, 0, 0, 3, 2, 5, 6])
np.in1d(values, [2, 3, 6])
array([ True, False, False, True, True, False, True])
4.4 File Input and Output with Arrays
# np.save()
# np.load() :
# 배열 데이터를 효과적으로 디스크에 저장하고
# 불러오는 함수이다. (___.npy)
arr = np.arange(10)
np.save('some_array', arr)
arr
del arr
np.load('some_array.npy')
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
arr
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-140-24a6d41c5b66> in <module>
----> 1 arr
NameError: name 'arr' is not defined
arr = np.load('some_array.npy')
arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
np.savez('array_archive.npz', a=arr, b=arr)
arch = np.load('array_archive.npz')
arch['b']
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
np.savez_compressed('arrays_compressed.npz', a=arr, b=arr)
!rm some_array.npy
!rm array_archive.npz
!rm arrays_compressed.npz
4.5 Linear Algebra
# np.dot() 함수
x = np.array([[1., 2., 3.], [4., 5., 6.]])
y = np.array([[6., 23.], [-1, 7], [8, 9]])
x
y
x.dot(y)
array([[ 28., 64.],
[ 67., 181.]])
np.dot(x, y)
array([[ 28., 64.],
[ 67., 181.]])
np.dot(x, np.ones(3))
x @ np.ones(3)
array([ 6., 15.])
from numpy.linalg import inv, qr
X = np.random.randn(5, 5)
mat = X.T.dot(X)
mat
array([[ 9.5217, -0.8643, 0.232 , 2.4084, -4.2914],
[-0.8643, 3.331 , 1.4328, 1.1822, -0.5939],
[ 0.232 , 1.4328, 2.4548, -0.2221, -0.6857],
[ 2.4084, 1.1822, -0.2221, 5.0444, 0.1331],
[-4.2914, -0.5939, -0.6857, 0.1331, 5.0562]])
# 역행렬
print(inv(mat))
mat.dot(inv(mat))
# 행렬 분할
q, r = qr(mat)
print(q)
print(r)
[[ 0.3283 0.2788 -0.1314 -0.2358 0.2997]
[ 0.2788 0.7034 -0.3893 -0.3224 0.2749]
[-0.1314 -0.3893 0.6427 0.1842 -0.0749]
[-0.2358 -0.3224 0.1842 0.4004 -0.2235]
[ 0.2997 0.2749 -0.0749 -0.2235 0.4802]]
[[-0.8853 0.1074 -0.0695 -0.0308 0.446 ]
[ 0.0804 -0.8387 0.1703 0.3062 0.4091]
[-0.0216 -0.3679 -0.8377 -0.3872 -0.1115]
[-0.2239 -0.3298 0.5114 -0.6848 -0.3326]
[ 0.399 0.2022 0.0533 -0.5352 0.7146]]
[[-10.7554 0.5003 -0.367 -3.1088 5.7537]
[ 0. -3.9237 -2.1454 -2.288 1.2681]
[ 0. 0. -1.9787 2.8069 1.1088]
[ 0. 0. 0. -3.1516 -2.5815]
[ 0. 0. 0. 0. 1.488 ]]
4.6 Pseudorandom Number Generation
# numpy.random module :
# random 내장 함수를 보강하여 다양한 종류의 확률분포
# 함수로부터 효과적으로 표본 값을 생성할 수 있다.
samples = np.random.normal(size=(4, 4))
samples
array([[ 0.6342, 1.2597, 0.9649, -0.4344],
[-0.8796, -0.6948, 1.2264, 0.4573],
[ 0.1157, 1.014 , -1.135 , -0.2634],
[ 1.3064, -1.6108, -1.0266, 1.2416]])
from random import normalvariate
N = 1000000
%timeit samples = [normalvariate(0, 1) for _ in range(N)]
%timeit np.random.normal(size=N)
1.62 s ± 35.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
58 ms ± 3.26 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
np.random.seed(1234)
rng = np.random.RandomState(1234)
rng.randn(10)
array([ 0.4714, -1.191 , 1.4327, -0.3127, -0.7206, 0.8872, 0.8596,
-0.6365, 0.0157, -2.2427])
4.7 Example: Random Walks
import random
position = 0
walk = [position]
steps = 1000
for i in range(steps):
step = 1 if random.randint(0, 1) else -1
position += step
walk.append(position)
plt.figure()
plt.plot(walk[:100])
np.random.seed(12345)
nsteps = 1000
draws = np.random.randint(0, 2, size=nsteps)
steps = np.where(draws > 0, 1, -1)
walk = steps.cumsum()
walk.min()
walk.max()
(np.abs(walk) >= 10).argmax()
4.7.1 Simulating Many Random Walks at Once
nwalks = 5000
nsteps = 1000
draws = np.random.randint(0, 2, size=(nwalks, nsteps)) # 0 or 1
steps = np.where(draws > 0, 1, -1)
walks = steps.cumsum(1)
walks
walks.max()
walks.min()
hits30 = (np.abs(walks) >= 30).any(1)
hits30
hits30.sum() # Number that hit 30 or -30
crossing_times = (np.abs(walks[hits30]) >= 30).argmax(1)
crossing_times.mean()
steps = np.random.normal(loc=0, scale=0.25,
size=(nwalks, nsteps))
댓글남기기