넘파이 라이브러리 불러오기
import numpy as np
numpy 라이브러리를 임포트하며, as np 는 일종의 별명입니다. 일일이 numpy라고 치는 것보다 np라고 줄여서 치는게 편하겠죠?
(참고로 아래 예제 코드에서는 이부분을 생략할 것입니다)
리스트 선언 및 numpy array로 변환
- np.array(list) : 리스트를 numpy array로 변환
import numpy as np
# 1차원 리스트 선언
list1 = [1,2,3,4,5]
# 2차원 리스트(행렬) 선언
list2 = [[1,2],[3,4]]
arr1 = np.array(list1) # 1차원 리스트
arr2 = np.array(list2) # 2차원 리스트
print(arr1)
>>>[1 2 3 4 5]
print(arr2)
>>>
[[1 2]
[3 4]]
0부터 9까지 숫자를 자동으로 생성한 array
- np.arange(값) : 값 길이의 array 생성
# 1번 방법
arr3 = np.array([0, 1,2,3,4,5,6,7,8,9])
print(arr3)
>>> [0 1 2 3 4 5 6 7 8 9]
# 2번 방법
arr3 = np.array(list(range(0,10)))
print(arr3)
>>> [0 1 2 3 4 5 6 7 8 9]
# 3번 방법
arr3 = np.arange(10)
print(arr3)
>>> [0 1 2 3 4 5 6 7 8 9]
10부터 99까지 숫자를 자동으로 생성한 array
# 위의 3번 방법 사용
arr4 = np.arange(10,100)
print(arr4)
>>>
[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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]
shape을 이용한 array의 배열 형태 확인
- shape : 배열의 형태를 알려줌
arr1 = np.array( [1,2,3,4,5] )
print(arr1)
>>> [1 2 3 4 5]
print(arr1.shape)
>>> (5,)
arr2 = np.array( [ [1,2] ,[3,4] ] )
print(arr2)
>>>
[[1 2]
[3 4]]
print(arr2.shape)
>>> (2, 2)
arr3 = np.arange(10)
print(arr3)
>>> [0 1 2 3 4 5 6 7 8 9]
print(arr3.shape)
>>>(10,)
arr4 = np.arange(10,100)
print(arr4)
>>>
[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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]
print(arr4.shape)
>>>(90,)
arr5 = np.array([[1,2], [3,4], [5,6]])
print(arr5)
>>>
[[1 2]
[3 4]
[5 6]]
print(arr5.shape)
>>> (3, 2)
array 배열 형태 바꾸기
- reshape 사용
# reshape 사용
arr6 = np.arange(1,10)
print(arr6)
>>>
[1 2 3 4 5 6 7 8 9]
arr7 = np.arange(1,10).reshape(3,3)
print(arr7)
>>>
[[1 2 3]
[4 5 6]
[7 8 9]]
reshape 응용 1
# row vector를 column vector로
arr8 = np.arange(6)
print(arr8)
>>> [0 1 2 3 4 5]
arr9 = np.arange(6).reshape(6,1)
print(arr9)
>>>
[[0]
[1]
[2]
[3]
[4]
[5]]
reshape 응용 2
# 펼치기
arr9 = np.array([[1,2,3,],
[4,5,6],
[7,8,9]])
print(arr9)
>>>
[[1 2 3]
[4 5 6]
[7 8 9]]
print(arr9.shape)
>>> (3, 3)
print(arr9.reshape(-1,)) # -1 과 길이 값인 9와 같은 결과
>>> [1 2 3 4 5 6 7 8 9]
print(arr9.reshape(9,)) # -1 과 길이 값인 9와 같은 결과
>>> [1 2 3 4 5 6 7 8 9]
array 더하기 및 합치기
- list와 array의 차이점 중 하나는 덧셈에서 나타난다. list 2개를 더하면, 두 리스트의 요소들이 한 리스트에 모이게 되지만, array 2개를 더하면, 인덱스에 맡게 요소들을 더하게 된다.
- concatenate : 두 개의 array의 요소들을 한 array로 합치기
# list의 덧셈
[1,2,3] + [4,5,6] = [1,2,3,4,5,6]
# array의 덧셈
[1,2,3] + [4,5,6] = [5,7,9]
# array 합치기
np.concatenate( [[1,2,3], [4,5,6]] )
>>> [1,2,3,4,5,6]
array 세로로 합치기(stacking)
- vstack 사용
# stacking vertically
arr10 = np.array([1, 2, 3])
arr11 = np.array([4, 5, 6])
print(np.concatenate([arr10,arr11]))
>>> [1 2 3 4 5 6]
print(np.vstack([arr10, arr11]))
>>>
[[1 2 3]
[4 5 6]]
array 가로로 합치기(stacking)
- hstack 사용
# stacking vertically
arr10 = np.array([1, 2, 3])
arr11 = np.array([4, 5, 6])
print(np.concatenate([arr10,arr11]))
>>> [1 2 3 4 5 6]
print(np.hstack([arr10, arr11]))
>>> [1 2 3 4 5 6]
List와 Array의 연산 결과 비교
- array 덧셈(+), 뺄셈(-), 곱셉(*), 나눗셈(/) 등 가능
# List
list1 = [1,2,3]
list2 = [4,5,6]
print(list1 + list2)
>>> [1, 2, 3, 4, 5, 6]
# Array
arr1 = np.array([1,2,3])
arr2 = np.array([4,5,6])
print(arr1 + arr2)
>>> [5 7 9]
print(arr1 - arr2)
>>> [-3 -3 -3]
print(arr1 / arr2)
>>> [0.25 0.4 0.5 ]
print(arr1 * arr2)
>>> [ 4 10 18]
Array 내적(dot product)
- array는 내적(@)이 가능함
# dot prod 내적uct
arr1 = np.array([1,2,3])
arr2 = np.array([4,5,6])
print(arr1 @ arr2)
>> 32
# (1 x 4) + (2 x 5) + (3 x 6) = 32
브로드캐스팅과 범용 함수(Brodcast and Universal Function)
브로드캐스팅(Brodcast)란
Numpy에서 브로드캐스팅은 일정 조건을 부합하는 다른 형태의 배열끼리 연산을 수행하는 것을 의미한다.
쉽게 말하면, 서로 크기가 다른 numpy array를 연산을 수행하는 것이다.
# (1,3) array
arr1 = np.array([1,2,3])
print(arr1)
>>> [1 2 3]
# (2,3) array
arr2 = np.array([[-1,-1,-1],
[1,1,1]])
print(arr2)
>>>
[[-1 -1 -1]
[ 1 1 1]]
## 과연 두 array를 더할수 있을까요?
# Numpy에서는 가능합니다
print( arr1 + arr2 )
>>>
[[0 1 2]
[2 3 4]]
# arr2 + arr1
# [ -1 -1 -1 ] + [ 1 2 3 ] = [ 0 1 2 ]
# [ 1 1 1 ] + [ 1 2 3 ] = [ 2 3 4 ]
범용 함수(Universal Function)란
브로드캐스팅 기능을 확장해서, numpy array의 모든 원소에 동일한 함수를 반복문으로 적용한것과 같은 효과를 내는 기능이다. sin, cos, exp, add 등 60개 이상의 범용 함수가 정의되어 있다.
아래는 범용 함수 사용 안할때와 범용 함수를 사용하는 비교 해보자
결론부터 말하자면 범용 함수를 사용하면 속도가 상승한다. 아래 코드를 보면 범용 함수를 사용 안할 때는 반복문을 사용하게 되는데, 반복문을 사용하게 되면서 속도가 감소하게 된다. 범용 함수를 사용하면 반복문 없이 실행이 된다.
# 범용함수 사용 안할 때
f = lambda x : 1/x
f(3) # 0.333
arr1 = np.array([1., 2., 3.])
for i in range(arr1.shape[0]):
arr1[i] = f(arr1[i])
print(arr1) # array([1. , 0.5 , 0.33333333])
# 범용함수 사용할 때
arr1 = np.array([1., 2., 3.])
print( 1/ arr1 ) # universal fuc
넘파이 메소드(Numpy Methods) 맛보기
5x3 행렬 랜덤으로 만들기
# 표준정규분포에서 random sampling을 한 원소를 가지는 5x3 행렬을 만든다.
mat1 = np.random.randn(5, 3)
print(mat1)
>>>
[[-2.0687591 -0.93356275 1.18107807]
[-1.17665873 1.72382876 -0.09030397]
[-0.88404004 1.48126292 -0.67397981]
[ 0.16004165 0.11851432 1.03285495]
[-0.26317026 0.5009752 1.72397358]]
절대값
# mat1에 절대값 씌우기
print(np.abs(mat1))
>>>
[[2.0687591 0.93356275 1.18107807]
[1.17665873 1.72382876 0.09030397]
[0.88404004 1.48126292 0.67397981]
[0.16004165 0.11851432 1.03285495]
[0.26317026 0.5009752 1.72397358]]
제곱하기
# mat1 제곱하기
print(np.square(mat1))
>>>
[[4.27976422 0.87153941 1.3949454 ]
[1.38452577 2.97158559 0.00815481]
[0.78152679 2.19413983 0.45424878]
[0.02561333 0.01404565 1.06678935]
[0.06925859 0.25097615 2.9720849 ]]
제곱근 구하기
# mat1의 제곱근 구하기
print(np.sqrt(mat1))
>>>
[[ nan nan 1.08677416]
[ nan 1.31294659 nan]
[ nan 1.21707145 nan]
[0.40005206 0.3442591 1.01629472]
[ nan 0.70779602 1.31300174]]
# RuntimeWarning: invalid value encountered in sqrt
# nan = not a number : 실수값이 표현 안되는 것
범용함수 기능과 반복문의 속도 차이 실험
범용 함수 X : 루프 1번을 돌았으며, 최고 속도는 2.24 초이다
범용 함수 O : 루프 100번을 돌았으며, 최고 속도는 2.08 밀리초이다
결론부터 말씀드리면 범용 함수를 사용하게 되면 약 100배는 더 빠르다(100배가 맞나..? 10배인가...)
또한, 범용 함수 X는 루프 1번만 돌고, 범용 함수 O는 루프 100번을 돌았다. 이 차이가 나타나는 이유는 같은 시간을 돌았을 때, 반복문을 사용한 범용 함수X가 느리다는 것도 간접적으로 알 수 있다.
def reverse_num(values):
output = np.empty(len(values))
for i in range(len(values)):
output[i] = 1.0 / values[i]
return output
# 1부터 100까지 범위에서 1000000개를 랜덤으로 뽑아서 array를 만듭니다.
big_array = np.random.randint(1, 100, 1000000)
print("범용함수 X : ")
%timeit reverse_num(big_array)
>>> 1 loop, best of 5: 2.24 s per loop
print("범용함수 O : ")
%timeit 1.0 / big_array
>>> 100 loops, best of 5: 2.08 ms per loop
'파이썬' 카테고리의 다른 글
[파이썬] 판다스(Pandas) 메서드 실습 (0) | 2022.04.18 |
---|---|
[파이썬] OOP 객체 지향 프로그래밍 (0) | 2022.04.18 |
[파이썬] 판다스(Pandas) 란 (0) | 2022.04.15 |
[파이썬] 넘파이(Numpy) 란 (0) | 2022.04.15 |
[파이썬] 힙(Heap) 이란 (0) | 2022.04.15 |