Numpy란¶
- "Numerical Python" or "Numeric Python"
Numpy의 특징과 장점¶
Python은 느리다. 왜? 그래서...
- 강력한 N차원 배열 객체. List보다 빠르다.(메모리구조)
- 정교한 브로드케스팅(Broadcast) 기능. 반복문 쓰지 않음
- 유용한 선형 대수학, 푸리에 변환 및 난수 기능
- C/C++ 및 포트란 코드 통합 도구
Numpy가 빠른 이유¶
- python 코드가 아니라, Numpy는 C코드로 작성
- 메모리 저장구조가 다름
- 반복문 사용하지 않고 배열 통해 바로 계산
- 벡터라이즈와 브로드캐스팅 사용
Numpy를 사용하려면?¶
import numpy as np
- 모듈(라이브러리)을 호출해 속성과 메서드 사용
- numpy.sum()을 간단히 별칭(alias)를 사용해 np.sum()으로 사용
배열(Array)이란¶
ndarray(n dimensional array)
Image("numpyarrays.PNG")
- 각 차원을 축(axis)라고 함
- 축의 개수는 차원의 개수인데 rank라고도 함.ndim
- 배열의 차원을 shape라고 하고 tuple로 표시(3,), (2,3)
- shape 안의 숫자는 각 차원에 있는 원소의 개수
- 전체 원소의 개수는 size
배열(Array) vs 행렬(Matrix)¶
Image("arraymatrix.PNG")
배열 만들기¶
array creation¶
a = np.array([0,1,2,3])
print(a)
[0 1 2 3]
type(a)
numpy.ndarray
- array함수는 np 라이브러리에 들어있다
- 입력값으로 list가 들어감
- 동일한 데이터형이어야 함
리스트를 array로 바꾸기¶
a = [0,1,2,3]
type(a)
list
- 리스트가 있다면 그 리스트를 입력값으로 넣어주기만 하면 됨
array_a = np.array(a)
type(array_a)
numpy.ndarray
array_a
array([0, 1, 2, 3])
Array의 attribute(속성)¶
a = np.array([0,1,2,3])
a.dtype
dtype('int32')
a.ndim
1
a.shape
(4,)
- 8bit = 1byte
- 32bit이므로 4byte가 한 칸
a.size
4
a.nbytes
16
nbytes의 의미¶
메모리크기반환
byte 수가 몇개인가?
a.dtype이 int32인 경우
int32는 32bit를 뜻하고 1byte는 8bit이므로 총 4bytes이다.a의 원소의 개수는 총 4개 이므로 4bytes 4를 하면 총 16bytes의 메모리를 사용하는 것으로 볼 수 있다.
**a.dtype이 int64인 경우**
int64는 64bit를 뜻하고 1byte는 8bit이므로 총 8bytes이다.a의 원소의 개수는 총 4개 이므로 8bytes 6을 하면 총 32bytes의 메모리를 사용하는 것으로 볼 수 있다.
a.itemsize
4
- size는 원소(element)의 개수
a = np.array([1,2,3,4])
a.dtype
dtype('int32')
int32의 의미¶
각 숫자마다 32개의 방이 부과됨.
1은 이진법으로 1이므로 방을 1개 차지해 방이 32개 남고
2,3는 이진법으로 10이므로 방을 2개 차지해 방이 30개 남고
4는 이진법으로 100이므로 방을 3개 차지해 방이 29개 남음
서버에서는 a.dtype이 int64로 뜸.
컴퓨터에 따라 a.dtype의 값이 다르게 나올 수 있음
a = np.array([1,2,3.5,4.1])
a.dtype
dtype('float64')
- 데이터형은 자동으로 할당됨(int32, float64)
a = np.array([1,2,3,4], int)
a
array([1, 2, 3, 4])
b = np.array([1,2,3,4], float)
b
array([1., 2., 3., 4.])
a.dtype
dtype('int32')
b.dtype
dtype('float64')
np.array([1,2,3.5,4.1], int)
array([1, 2, 3, 4])
Python vs Numpy¶
np.array([1,2,3.5, 4.1], float64)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[85], line 1
----> 1 np.array([1,2,3.5, 4.1], float64)
NameError: name 'float64' is not defined
- Python의 데이터형은
int, float, str, boolean, complex number, list, tuple, set, dict
Image("datatype.png")
- 마무리 퀴즈
# 설치된 Numpy 라이브러리 사용하려면 가장 먼저 해야할 일은?
import numpy as np
# array([0,1,2,3])와 같이 출력되도록 1차원 배열 만들기
a = np.array([0,1,2,3], int)
a
array([0, 1, 2, 3])
# Array 객체에서 속성의 종류는 무엇이 있었는가? 3개이상
a.dtype # 배열 원소 종류
a.ndim # 배열의 차원 수 or 배열의 축 수
a.shape # 배열 각 차원의 크기를 (n,m) 형태 튜플로
추가학습(다음 블로그 참고)¶
배열 선언¶
a = [1,2,3,4,5] #List
type(a)
list
b = np.array([1,2,3,4,5]) # Array
type(b)
numpy.ndarray
c = np.array(1,2,3,4,5) # 옳지 않은 방법
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[90], line 1
----> 1 c = np.array(1,2,3,4,5)
TypeError: array() takes from 1 to 2 positional arguments but 5 were given
numpy를 통해 배열은 선언하기 위해서는 np.array() 사용
c의 경우 에러 발생. 배열 선언 시에는 꼭 대괄호 [] 사용
배열의 차원¶
넘파이의 각 차원은 axes(축)으로 불림
np.array([1,2,3,4,5])
array([1, 2, 3, 4, 5])
위 배열은 1차원 배열이며 1차원 배열의 길이는 5
np.array([[1,2,3,4,5],[6,7,8,9,10]])
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10]])
위 배열은 2차원 배열
첫 번째 차원은 [1,2,3,4,5]으로 길이가 5
두 번째 차원은 [6,7,8,9,10]으로 길이가 5
여기에 계속해서 차원 추가 가능
따라서 1,2,3,...n개의 차원으로 계속해서 많은 차원의 배열 선언 가능
나중에 딥러닝/머신러닝 진행 시 각 차원이 너무 많아져서 계산이 느려지는 문제 직면
넘파이 객체¶
넘파이의 class는 ndarray이며 일반적으로는 그냥 array 또는 배열이라고 이야기
ndarry 객체의 속성은 다음과 같다
ndarray.ndim¶
배열의 차원 수 or 배열의 축 수
b = np.array([1,2,3,4,5])
b.ndim
1
c = np.array([[1.,0.,0.],
[0.,1.,2.]])
c.ndim
2
ndarray.shape¶
배열 각 차원의 크기를 튜플 형태로 표현
n행과 m열 행렬의 경우 (n, m) 형태의 튜플로 나타냄
b = np.array([1,2,3,4,5])
c = np.array([[1.,0.,0.],
[0.,1.,2.]])
d = np.array([[1.,0.,0.],
[0.,1.,2.],
[3.,4.,7.],
[3.,0.,1.]])
b.shape
(5,)
c.shape
(2, 3)
d.shape
(4, 3)
배열 b는 1차원 길이가 5인 배열이므로 shape를 보면 (5,)
배열 c는 2차원이며 각 차원의 길이가 3인 배열이므로 (2,3). 2행 3열로 이루어진 배열
배열 d는 4차원이며 각 차원의 길이가 3인 배열이므로 (4,3). 4행 3열로 이루어진 배열
ndarry.shape가 (5,)일 때와 (1,5)일 때의 차이¶
a = np.array([1,2,3,4,5])
a
array([1, 2, 3, 4, 5])
a.shape
(5,)
- a는 원소의 개수가 총 5개인 1차원 배열
b = np.array([[1,2,3,4,5]])
b
array([[1, 2, 3, 4, 5]])
b.shape
(1, 5)
ndarray.dtype¶
배열의 원소의 종류를 알 수 있음.
기본적으로 넘파이의 원소들은 모두 같은 데이터 타입을 가짐
numpy.int32, numpy.int16, numpy.float64 등이 있음
b = np.array([1,2,3,4,5])
c = np.array([[1., 0., 0.],
[0., 1., 2.]])
b.dtype
dtype('int32')
c.dtype
dtype('float64')
배열 b는 정수형 요소들로 이루어져 있으므로 data의 type은 int32로 출력
배열 c는 실수형 데이터 타입으로 이루어져 있어 data의 type은 float64으로 출력
2차원, 3차원 배열 만들기¶
- np.array() 함수를 써서 만들기
- arange()와 reshap()를 써서 만들기
- 3차원 배열 만들기
2차원 배열 만들기 1¶
np.array()함수 써서 만들기¶
arr1 = np.array([[1,2], [3,4]])
arr2 = np.array([[5,6], [7,8]])
arr1
array([[1, 2],
[3, 4]])
arr2
array([[5, 6],
[7, 8]])
- 중첩리스트
2차원 배열 만들기 2¶
arange와 reshape로 만들기¶
a = np.arange(8)
a.shape
(8,)
a.reshape(2,4)
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
np.arange(8).reshape(2,4)
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
np.arange(6, dtype = np.float32).reshape(2,3)
array([[0., 1., 2.],
[3., 4., 5.]], dtype=float32)
- arange()를 쓰면 데이터타입도 정할 수 있음
3차원 배열 만들기¶
n = np.array([[[1,2],[3,4]],
[[5,6],[7,8]]])
n
array([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])
n.shape
(2, 2, 2)
np.arange(8).reshape(2,2,2)
array([[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]])
np.arange(24).reshape(2,3,4)
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]]])
np.arange(24).reshape(2,3,4).ndim
3
차원의 의미¶
ndim은 배열의 차원 수 혹은 배열의 축 수를 의미한다.
여기서 차원의 수는 reshape함수에 들어가는 매개변수의 개수를 뜻한다.
np.arange(24).reshape(2,3,4).ndim # x,y,z
3
np.arange(12).reshape(2,6).ndim # x,y
2
np.arange(6).reshape(6,).ndim # x
1
배열의 연산(Operation)¶
- 리스트의 연산과 비슷하지만, 약간 다르다
- numpy 함수를 쓰는 것보다 객체.함수()가 편리
- Numpy의 연산은 원소들끼리 이루어짐 element wise
- array의 형태(shape)가 안맞으면, 자동으로 맞추어 주기도 함. broadcasting
List Operation 연습¶
a = [1,2,3,4]
b = [5,6,7,8]
print(a,b)
type(a)
[1, 2, 3, 4] [5, 6, 7, 8]
list
a + b
[1, 2, 3, 4, 5, 6, 7, 8]
a - b
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[159], line 1
----> 1 a - b
TypeError: unsupported operand type(s) for -: 'list' and 'list'
a*3
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
a[1]
2
a[1] = 10
a
[1, 10, 3, 4]
1D Array Operation¶
1D Array¶
- 사칙연산 +, -, *, /
- 거듭제곱, 제곱근
- 지수, 로그
- 삼각함수
a = np.array([1,2,3,4])
b = np.array([5,6,7,8])
print(a,b)
[1 2 3 4] [5 6 7 8]
type(a)
numpy.ndarray
a.shape
(4,)
a.size
4
1차원 array의 사칙연산¶
a+b
array([ 6, 8, 10, 12])
np.add(a,b)
array([ 6, 8, 10, 12])
a-b
array([-4, -4, -4, -4])
np.subtract(a,b)
array([-4, -4, -4, -4])
- element wise
a*b
array([ 5, 12, 21, 32])
np.multiply(a,b)
array([ 5, 12, 21, 32])
a/b
array([0.2 , 0.33333333, 0.42857143, 0.5 ])
np.divide(a,b)
array([0.2 , 0.33333333, 0.42857143, 0.5 ])
a*b
array([ 5, 12, 21, 32])
a**b
array([ 1, 64, 2187, 65536])
a*3
array([ 3, 6, 9, 12])
a+1
array([2, 3, 4, 5])
- broadcasting
2D Array Operation¶
arr1 = np.array([[1,2], [3,4]])
arr2 = np.array([[5,6], [7,8]])
arr1
array([[1, 2],
[3, 4]])
arr2
array([[5, 6],
[7, 8]])
2차원 array의 곱셈¶
np.multiply(arr1, arr2)
array([[ 5, 12],
[21, 32]])
arr1*arr2
array([[ 5, 12],
[21, 32]])
matrix의 곱셈¶
- 행렬의 곱셈 참고
Image("matrixmul.png")
np.matmul(arr1, arr2)
array([[19, 22],
[43, 50]])
arr1@arr2
array([[19, 22],
[43, 50]])
- 2X2여서 np.dot(arr1, arr2)도 위와 같다
np.dot(arr1, arr2) #np.dot은 2개의 input만을 받음
array([[19, 22],
[43, 50]])
- np.dot 참고출처
- 마무리 퀴즈
#다음과 같이 출력되도록 2차원 배열을 2가지 방법으로 만들기
#array([[5,6],
# [7,8]])
#1.
arr1 = np.array([[5,6], [7,8]])
arr1
array([[5, 6],
[7, 8]])
arr2 = np.arange(5,9).reshape(2,2)
arr2
array([[5, 6],
[7, 8]])
#2
arr = np.arange(36).reshape(3,4,3)
Numpy 내장함수를 이용해 array 만들기¶
- arange
- linspace
- zeros
- ones
- empty
- full
- tile
- **_like
arange¶
- arange(start, stop, step, dtype)
b = np.arange(1,9,2)
b
array([1, 3, 5, 7])
a = np.arange(9, dtype = np.float32)
a
array([0., 1., 2., 3., 4., 5., 6., 7., 8.], dtype=float32)
linspace¶
- linspace(start, stop, numbers of element)
c = np.linspace(0,1,6)
c
array([0. , 0.2, 0.4, 0.6, 0.8, 1. ])
d = np.linspace(0,1,5, endpoint = False)
d
array([0. , 0.2, 0.4, 0.6, 0.8])
endpoint의 의미¶
endpoint=True 혹은 endpoint=False를 적을 수 있는데
이것이 적혀있지 않으면 디폴트(Default)로 True이며,
이는 stop으로 주어진 값을 포함시킬 것인지 아닌지를 선택하는 옵션
np.ones¶
- ones(shape [, dtype, order])
a = np.ones((3,3), int) # shape (3,3)은 튜플
a
array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
a*3
array([[3, 3, 3],
[3, 3, 3],
[3, 3, 3]])
np.zeros¶
- zeros(shape [, dtype, order])
b = np.zeros((3,3))
b
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
b[2,0] = 3 # sparse matrix : 행렬의 대부분의 요소가 0인 행렬
b
array([[0., 0., 0.],
[0., 0., 0.],
[3., 0., 0.]])
np.diag¶
- diagonal은 대각선
a = np.diag([1,2,3])
a
array([[1, 0, 0],
[0, 2, 0],
[0, 0, 3]])
c = np.arange(9).reshape(3,3)
np.diag(c)
array([0, 4, 8])
np.identity¶
np.identity()는 정사각행렬이 정해져 있다¶
- np.identity()는 대각행렬이 1이고 나머지는 모두 0인 정사각행렬
d = np.identity(4)
d
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
np.identity(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
np.eye(4)와 np.identity(4)는 같다¶
d = np.eye(4,3)
d
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
[0., 0., 0.]])
np.eye(4,3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
[0., 0., 0.]])
np.eye(4)
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
- np.identity()와 np.eye()의 차이
Identity 행렬은 항상 nxn의 행렬이라면, eye는 원하는 NxM으로 행렬을 만들 수 있다.
np.tile¶
- np.tile(A, repeat_shape)
- A 배열이 repeat_shape 형태로 반복되어 쌓인 형태가 반환
a = np.array([0,1,2])
np.tile(a,2) # repeat a 2 times
array([0, 1, 2, 0, 1, 2])
np.tile(a, (3,2))
array([[0, 1, 2, 0, 1, 2],
[0, 1, 2, 0, 1, 2],
[0, 1, 2, 0, 1, 2]])
np.full¶
- np.full(shape,fill_value)
- 모든 값이 사용자 지정값인 배열 생성
np.full((2,2),3)
array([[3, 3],
[3, 3]])
np.full((4,3),2)
array([[2, 2, 2],
[2, 2, 2],
[2, 2, 2],
[2, 2, 2]])
np.empty¶
- 선언한 행렬에, 무작위의 값을 모든 값에 입력
np.empty((2,3)) # null에 해당하는 주소값, 초기화 안함
array([[6.23042070e-307, 4.67296746e-307, 1.69121096e-306],
[9.34609111e-307, 1.42413555e-306, 1.78019082e-306]])
***_like() 함수로 배열만들기¶
- zeros_like()
- ones_like()
- empty_like()
- full_like()
zeros_like¶
- 형태와 데이터타입을 유지하면서 0으로 채움
a = np.arange(6).reshape(2,3)
a
array([[0, 1, 2],
[3, 4, 5]])
b = np.arange(3, dtype = np.float)
print(b)
b.dtype
[0. 1. 2.]
C:\Users\user\AppData\Local\Temp\ipykernel_9424\157655229.py:1: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
b = np.arange(3, dtype = np.float)
dtype('float64')
np.zeros_like(a)
array([[0, 0, 0],
[0, 0, 0]])
np.zeros_like(b)
array([0., 0., 0.])
ones_like, empty_like¶
- 형태와 데이터타입을 유지하면서..
np.ones_like(a)
array([[1, 1, 1],
[1, 1, 1]])
np.ones_like(b)
array([1., 1., 1.])
np.empty_like(a)
array([[ 0, 1072693248, 0],
[1072693248, 0, 1072693248]])
np.empty_like(b)
array([1., 1., 1.])
full_like¶
- 형태와 데이터타입을 유지하면서..
np.full_like(a)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[255], line 1
----> 1 np.full_like(a)
File <__array_function__ internals>:179, in full_like(*args, **kwargs)
TypeError: _full_like_dispatcher() missing 1 required positional argument: 'fill_value'
np.full_like(a,3)
array([[3, 3, 3],
[3, 3, 3]])
np.full_like(b, 3.1)
array([3.1, 3.1, 3.1])
copy()의 두가지 방법¶
- 기본 배열로부터 새로운 배열을 생성하기 위해서는 copy 함수로 명시적으로 사용해야 함
- copy 함수로 복사한 배열은 원본 배열과 완전히 다른 새로운 객체
- slice, indexing은 새로운 객체가 아닌 기존 배열의 뷰(View)
- 반환한 배열의 값을 변경하면 원본 배열이 변경됨
copy() 방법1¶
A = np.arange(1,6)
A
array([1, 2, 3, 4, 5])
B = A.copy() # B = np.copy(A)
B
array([1, 2, 3, 4, 5])
B = np.copy(A)
B
array([1, 2, 3, 4, 5])
B[3] = 0
B
array([1, 2, 3, 0, 5])
A #A는 안변함
array([1, 2, 3, 4, 5])
copy() 방법2¶
C = A #이렇게 할당
C
array([1, 2, 3, 4, 5])
C[3] = 0
C
array([1, 2, 3, 0, 5])
A #A도 변함 View
array([1, 2, 3, 0, 5])
- 퀴즈
np.arange(1,9,2)
array([1, 3, 5, 7])
np.linspace(0,1,6)
array([0. , 0.2, 0.4, 0.6, 0.8, 1. ])
np.ones((3,3), int)
array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
# ***like에는 어떤 것들이 있나?
zeros_like, ones_like, empty_like, full_like
#copy와 비교해 view란?
copy 깊은복사 view 얕은복사
배열의 결합. stack으로 만들기¶
- hstack
- vstack
- dstack
- concatenate
stack이란:FIFO. 선착순의 반대
vstack¶
- 배열을 세로로 결합
a = np.arange(5)
a*10
array([ 0, 10, 20, 30, 40])
np.vstack([a*10, a*20])
array([[ 0, 10, 20, 30, 40],
[ 0, 20, 40, 60, 80]])
np.vstack([a*10, a*20]).shape
(2, 5)
hstack¶
- 배열을 가로로 결합
np.hstack([a*10, a*20])
array([ 0, 10, 20, 30, 40, 0, 20, 40, 60, 80])
import numpy as np
a = [1,2,3]
b = [4,5,6]
np.vstack([a,b]) # 리스트이거나
array([[1, 2, 3],
[4, 5, 6]])
a = np.array([1,2,3])
b = np.array([4,5,6])
np.vstack([a,b]) # array이거나
array([[1, 2, 3],
[4, 5, 6]])
dstack¶
np.dstack((a,b)) # stack arrays in sequence depth wise
array([[[1, 2]],
[[2, 3]],
[[3, 4]]])
a = np.array([[1],[2],[3]])
b = np.array([[2],[3],[4]])
print(a)
[[1]
[2]
[3]]
print(b)
[[2]
[3]
[4]]
np.dstack((a,b))
array([[[1, 2]],
[[2, 3]],
[[3, 4]]])
배열의 분리 spliting¶
- 수평분리 hsplit와 수직분리 vsplit
from IPython.display import Image
Image("hsplit.png")
- np.hsplit(a,2)
a = np.arange(1,25).reshape((4,6))
a
array([[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12],
[13, 14, 15, 16, 17, 18],
[19, 20, 21, 22, 23, 24]])
a.shape
(4, 6)
a[:,:3]
array([[ 1, 2, 3],
[ 7, 8, 9],
[13, 14, 15],
[19, 20, 21]])
a[:,3:]
array([[ 4, 5, 6],
[10, 11, 12],
[16, 17, 18],
[22, 23, 24]])
- np.vsplit(a,2)
b = np.arange(1,25).reshape((4,6))
b.shape
(4, 6)
b[:2]
array([[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12]])
b[2:]
array([[13, 14, 15, 16, 17, 18],
[19, 20, 21, 22, 23, 24]])
hsplit¶
a = np.arange(1,25).reshape((4,6))
a
array([[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12],
[13, 14, 15, 16, 17, 18],
[19, 20, 21, 22, 23, 24]])
np.hsplit(a,2)
[array([[ 1, 2, 3],
[ 7, 8, 9],
[13, 14, 15],
[19, 20, 21]]),
array([[ 4, 5, 6],
[10, 11, 12],
[16, 17, 18],
[22, 23, 24]])]
np.hsplit(a,3)
[array([[ 1, 2],
[ 7, 8],
[13, 14],
[19, 20]]),
array([[ 3, 4],
[ 9, 10],
[15, 16],
[21, 22]]),
array([[ 5, 6],
[11, 12],
[17, 18],
[23, 24]])]
vsplit¶
np.vsplit(a,2)
[array([[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12]]),
array([[13, 14, 15, 16, 17, 18],
[19, 20, 21, 22, 23, 24]])]
np.vsplit(a,3)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[35], line 1
----> 1 np.vsplit(a,3)
File <__array_function__ internals>:180, in vsplit(*args, **kwargs)
File ~\anaconda3\lib\site-packages\numpy\lib\shape_base.py:997, in vsplit(ary, indices_or_sections)
995 if _nx.ndim(ary) < 2:
996 raise ValueError('vsplit only works on arrays of 2 or more dimensions')
--> 997 return split(ary, indices_or_sections, 0)
File <__array_function__ internals>:180, in split(*args, **kwargs)
File ~\anaconda3\lib\site-packages\numpy\lib\shape_base.py:872, in split(ary, indices_or_sections, axis)
870 N = ary.shape[axis]
871 if N % sections:
--> 872 raise ValueError(
873 'array split does not result in an equal division') from None
874 return array_split(ary, indices_or_sections, axis)
ValueError: array split does not result in an equal division
np.vsplit(a,4)
[array([[1, 2, 3, 4, 5, 6]]),
array([[ 7, 8, 9, 10, 11, 12]]),
array([[13, 14, 15, 16, 17, 18]]),
array([[19, 20, 21, 22, 23, 24]])]
Numpy의 shape 변경 함수¶
- reshape
- flatten
- ravel
reshape¶
a = np.arange(20)
a
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
b = np.reshape(a, (4,5)) # better expression
a = np.arange(24)
a
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])
a.reshape(2,12)
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]])
a.reshape(2,-1) # -1은 자동으로 맞추어 주라는 뜻
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]])
a.reshape(-1, 6)
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]])
Image("reshape.png")
flatten, ravel¶
- flatten, ravel 모두 다차원 배열을 1차원으로 바꿈
- flatten은 copy(복사)하므로 원본 변경 X
- ravel은 변경하면 원본도 같이 변경
c = b.flatten() #return a copy
c
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
d = b.ravel() # flatten과 차이점
d
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19])
c[3] = 30
print(c)
[ 0 1 2 30 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
print(b)
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
d[3] = 30
print(d)
[ 0 1 2 30 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
print(b)
[[ 0 1 2 30 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
transpose¶
Image("transpose.png")
import numpy as np
a = np.array([[0,1,2,3]])
a
array([[0, 1, 2, 3]])
b = a.T #T attribute 사용
b
array([[0],
[1],
[2],
[3]])
a = np.arange(6).reshape(2,3)
a
array([[0, 1, 2],
[3, 4, 5]])
np.transpose(a) # transpose() 함수 사용
array([[0, 3],
[1, 4],
[2, 5]])
- 마무리 간단퀴즈
# a = np.array([1,2,3])이고 b = np.array([4,5,6])일 때,
# array([[1,2,3],
# [4,5,6]])이 되도록 결합
a = np.array([1,2,3])
b = np.array([4,5,6])
np.vstack([a,b])
array([[1, 2, 3],
[4, 5, 6]])
# np.flatten()과 np.ravel()이 차이
flatten과는 다르게 ravel은 같은 메모리 공유
# [[1,2], [[1,3]
# [3,4]]인 배열을 만들고 전치하여 [2,4]]로 만들기
a = np.array([[1,2],[3,4]])
b = a.T
b
array([[1, 3],
[2, 4]])
두 배열 비교¶
- 같다(==)
- 크다, 작다
- 배열 전체를 하나로 비교 (np.array_equal)
Comparison¶
a = np.array([1,2,3,4])
b = np.array([3,4,5,6])
print(a,b)
type(a)
[1 2 3 4] [3 4 5 6]
numpy.ndarray
a = np.array([1,2,3,4])
b = np.array([3,4,5,6])
a == b # 각각 비교
array([False, False, False, False])
a > b
array([False, False, False, False])
np.array_equal(a,b)
False
정렬하기 sort()¶
- numpy.sort()와 객체.sort()는 다르다.
- 1차원 배열의 정렬, 역순으로 정렬
- 2차원 배열의 정렬과 축기준으로 정렬하기
np.sort()¶
np.sort() 함수와 객체.sort()의 차이¶
a = np.array([4,2,6,5,1,3,0])
a
array([4, 2, 6, 5, 1, 3, 0])
np.sort(a) #View
array([0, 1, 2, 3, 4, 5, 6])
a
array([4, 2, 6, 5, 1, 3, 0])
a.sort() #배열 자체를 정렬
a
array([0, 1, 2, 3, 4, 5, 6])
역순 정렬¶
a = np.array([4,2,6,5,1,3,0])
np.sort(a)[::-1] ## 정렬한 후 step이 뒤에서 읽어옴
array([6, 5, 4, 3, 2, 1, 0])
축을 지정해 정렬¶
x = np.array([[2,1,6],
[0,7,4],
[5,3,2]])
x
array([[2, 1, 6],
[0, 7, 4],
[5, 3, 2]])
np.sort(x, axis=0) # row - wise 행끼리
array([[0, 1, 2],
[2, 3, 4],
[5, 7, 6]])
np.sort(x, axis=1) #coloum - wise 열끼리
array([[1, 2, 6],
[0, 4, 7],
[2, 3, 5]])
인덱싱(Indexing)¶
1D Indexing¶
np.array([0,1,2,3])
array([0, 1, 2, 3])
a = np.array([0,1,2,3])
a.ndim #차원의 수
1
a.size
4
a.nbytes
16
a.dtype
dtype('int32')
a[0] = 10
a
array([10, 1, 2, 3])
a[0] = 10.5
a
array([10, 1, 2, 3])
2D Indexing¶
a = np.array([[0,1,2,3],
[10,11,12,13]])
a
array([[ 0, 1, 2, 3],
[10, 11, 12, 13]])
a.ndim
2
a.shape
(2, 4)
a.size
8
a[1,3]
13
a[1,3] = -1 # a[1,3]자리에 -1대입
a
array([[ 0, 1, 2, 3],
[10, 11, 12, -1]])
a[1]
array([10, 11, 12, -1])
a[1,]
array([10, 11, 12, -1])
a[,1]
Cell In[68], line 1
a[,1]
^
SyntaxError: invalid syntax
a[:,1]
array([ 1, 11])
- 간단 퀴즈
a = np.arange(0, 60).reshape(6, 10)[:,:6]
a
array([[ 0, 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55]])
a = np.array([0,1,2,3,4,5])
b = np.array([[0],[10],[20],[30],[40],[50]])
a = a+b
a
array([[ 0, 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55]])
a[:,2]
array([ 2, 12, 22, 32, 42, 52])
슬라이싱(Slicing)¶
- var[lower:upper:step] upper은 포함안돼
1D slicing¶
- 1차원 배열은 리스트에서의 slicing과 같다.
a = np.array([10,11,12,13,14])
a
array([10, 11, 12, 13, 14])
a = np.array([10,11,12,13,14])
a
array([10, 11, 12, 13, 14])
a[1:3]
array([11, 12])
a[1:-2]
array([11, 12])
a[-4:3]
array([11, 12])
a[-2:1]
array([], dtype=int32)
a = np.array([10,11,12,13,14])
a
array([10, 11, 12, 13, 14])
a[:3]
array([10, 11, 12])
a[-2:]
array([13, 14])
a[::2]
array([10, 12, 14])
2D slicing¶
- 2차원 배열은 1차원 배열이 2개 있는 것이다. (and 연산)
a = np.array([0,1,2,3,4,5])
b = [[0], [10], [20], [30], [40], [50]]
a = a+b
a
array([[ 0, 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55]])
a[4:,4:]
array([[44, 45],
[54, 55]])
a[:,2]
array([ 2, 12, 22, 32, 42, 52])
a[2::2,::2]
array([[20, 22, 24],
[40, 42, 44]])
var[lower:upper:step]
slicing으로 값 수정하기¶
a = np.array([0,1,2,3,4])
a
array([0, 1, 2, 3, 4])
a[-2:]
array([3, 4])
a[-2:] = [13,14]
a
array([ 0, 1, 2, 13, 14])
a[-2:]=11
a
array([ 0, 1, 2, 11, 11])
slicing은 원본 View¶
- slice한 것은 복사품이 아니라, 원본의 참조
a = np.array([0,1,2,3,4])
a
array([0, 1, 2, 3, 4])
b = a[2:4]
b
array([2, 3])
b[0] = 10
b
array([10, 3])
a
array([ 0, 1, 10, 3, 4])
- changing b change a
그림으로 정리¶
from IPython.display import Image
Image("slicing.png")
- 마무리 퀴즈
a = np.array([0,1,2,3,4])
b = np.array([[0], [5],[10], [15], [20]])
a =a+b
a[4]
array([20, 21, 22, 23, 24])
a[:,1:4:2]
array([[ 1, 3],
[ 6, 8],
[11, 13],
[16, 18],
[21, 23]])
a[1:4:2,:4:2]
array([[ 5, 7],
[15, 17]])
팬시 인덱싱(Fancy Indexing)이란¶
- 정수 배열을 indexer로 사용해서 Indexing하는 방법
- 정수나 불린(Boolean) 값을 가지는 다른 Numpy 배열로 배열을 인덱싱할 수 있는 기능
- indexing by position
- indexing by boolean
- indexing by condition
Fancy Indexing.position¶
a = np.arange(0,80,step=10)
a
array([ 0, 10, 20, 30, 40, 50, 60, 70])
indices = [1,2,-3]
a[indices] = 99 # index에 있는 값 바꾸기
a
array([ 0, 99, 99, 30, 40, 99, 60, 70])
a[indices]
array([99, 99, 99])
a[[1,2,-3]]
array([99, 99, 99])
Fancy Indexing.boolean¶
a = np.arange(0,80,step=10)
a
array([ 0, 10, 20, 30, 40, 50, 60, 70])
mask = np.array([0,1,1,0,0,1,0,0], dtype = bool)
a[mask]
array([10, 20, 50])
mask = np.array([False, True, True, False, False, True, False, False])
a[mask]
array([10, 20, 50])
a = np.arange(0,80,step = 10)
a
array([ 0, 10, 20, 30, 40, 50, 60, 70])
a>40
array([False, False, False, False, False, True, True, True])
a[a>40]
array([50, 60, 70])
mask = a>40
a[mask]
array([50, 60, 70])
2차원 팬시 인덱싱¶
# 미리 알아두어야 할 것
a = np.arange(12).reshape(3,4)
a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
[a[0,1], a[1,2], a[2,0], a[2,3]]
[1, 6, 8, 11]
a[[0,1,2,2], [1,2,0,3]] # (0,1)(1,2)(2,0)(2,3)
array([ 1, 6, 8, 11])
a = np.arange(0, 60).reshape(6,10)[:,:6]
a
array([[ 0, 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55]])
a[[0,1,2,3,4],
[1,2,3,4,5]]
array([ 1, 12, 23, 34, 45])
a[3:, [0,2,5]]
array([[30, 32, 35],
[40, 42, 45],
[50, 52, 55]])
mask = np.array([1,0,1,0,0,1], dtype = bool)
a[3:, mask]
array([[30, 32, 35],
[40, 42, 45],
[50, 52, 55]])
a[mask, 2]
array([ 2, 22, 52])
- 마무리 퀴즈
a = np.array([0,1,2,3,4])
b = [[0],[5],[10],[15],[20]]
a = a+b
a
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]])
a[[0,1,2,3],[1,2,3,4]]
array([ 1, 7, 13, 19])
브로드캐스팅(Broadcasting)¶
- 차원(dimension)이 다른 두 배열의 연산에서
- 낮은 차원의 배열이 차원을 맞추어 주도록 변화
- 데이터의 복사를 하지 않으므로 빠르다
브로드캐스팅¶
Image("broadcasting.png")
a = np.ones((3,5))
a
array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
b = np.ones((5,))
b
array([1., 1., 1., 1., 1.])
a+b
array([[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.],
[2., 2., 2., 2., 2.]])
a+2
array([[3., 3., 3., 3., 3.],
[3., 3., 3., 3., 3.],
[3., 3., 3., 3., 3.]])
a = np.ones((3,5))
a
array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
b = np.array([1,2])
b
array([1, 2])
a+b
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[204], line 1
----> 1 a+b
ValueError: operands could not be broadcast together with shapes (3,5) (2,)
Image("broadcastingerror.png")
a = np.array([[0], [10], [20], [30]])
b = np.array([0,1,2])
a+b
array([[ 0, 1, 2],
[10, 11, 12],
[20, 21, 22],
[30, 31, 32]])
Array Calculation(=Computation) by Universal Functions¶
- 수학함수 : sum, prod, min, max, argmin, argmax
- 통계함수 : mean, std, var
- 진리값 : any, all
sum()¶
a = np.array([[1,2,3], [4,5,6]])
a
array([[1, 2, 3],
[4, 5, 6]])
np.sum(a)
21
np.sum(a)
21
a.shape
(2, 3)
np.sum(a,axis=0) #행끼리 더해
array([5, 7, 9])
np.sum(a,axis=1) #열끼리 더해
array([ 6, 15])
min(), max()¶
np.min(a)
1
np.min(a, axis = 0)
array([1, 2, 3])
np.min(a, axis=1)
array([1, 4])
np.max(a)
6
np.max(a,axis=0)
array([4, 5, 6])
np.max(a,axis=1)
array([3, 6])
argmin(), argmax¶
- argmin(): 가장 작은 원소의 인덱스 반환
- argmax(): 가장 큰 원소의 인덱스 반환
np.argmin(a)
0
np.argmax(a)
5
mean(), std(), var()¶
np.mean(a)
3.5
a.mean()
3.5
np.mean(a,axis=0)
array([2.5, 3.5, 4.5])
a.mean(axis=0)
array([2.5, 3.5, 4.5])
np.mean(a, axis=1)
array([2., 5.])
a.std()
1.707825127659933
a.std(axis=0)
array([1.5, 1.5, 1.5])
a.std(axis=1)
array([0.81649658, 0.81649658])
a.var(axis=0)
array([2.25, 2.25, 2.25])
where¶
a = np.array([6,8,7,9,10], dtype = int)
a
array([ 6, 8, 7, 9, 10])
np.where(a>7) #return index
(array([1, 3, 4], dtype=int64),)
index = np.where(a>7)
print(index) # index
a[index] # value
(array([1, 3, 4], dtype=int64),)
array([ 8, 9, 10])
a = np.arange(1,7).reshape(2,3)
a
array([[1, 2, 3],
[4, 5, 6]])
np.where(a>2)
(array([0, 1, 1, 1], dtype=int64), array([2, 0, 1, 2], dtype=int64))
a[np.where(a>2)]
array([3, 4, 5, 6])
- 마무리 퀴즈
- 아래와 같은 array를 만듦
a = np.arange(-15, 15).reshape(5,6)**2
a
array([[225, 196, 169, 144, 121, 100],
[ 81, 64, 49, 36, 25, 16],
[ 9, 4, 1, 0, 1, 4],
[ 9, 16, 25, 36, 49, 64],
[ 81, 100, 121, 144, 169, 196]])
1. 각 행별로 최댓값은 각각 얼마?¶
np.max(a, axis = 1)
array([225, 81, 9, 64, 196])
2. 각 열별로 평균?¶
np.mean(a, axis=0)
array([81., 76., 73., 72., 73., 76.])
파이썬은 왜 느린가? 넘파이는 왜 빠른가?¶
- Numpy의 메모리 저장 위치 vs Python
- Numpy does not make new one (strides)
- C is faster than any interpreter language
strides¶
strides는 '걸음걸이'라는 뜻을 가지고 있는 단어
numpy에서는 각 dimensions를 건너가는데 몇 bytes나 뛰어넘어야 하는지에 대한 정보
예를 들어 [[1,2,3],[4,5,6]]이라는 2차원의 array가 있음
strides를 사용하면 (dimensions 간의 간격, 앨리먼트 간의 간격)으로 결과 출력 각 dimension의 간격은 [1,2,3]의 용량과 같으므로 4바이트인 int32형 3개 = 12bytes인 것
a = np.arange(6)
a
array([0, 1, 2, 3, 4, 5])
a.strides
(4,)
b = a.reshape(2,3)
b
array([[0, 1, 2],
[3, 4, 5]])
b.strides
(12, 4)
메모리 저장구조¶
a = np.array([[0,1,2],
[3,4,5]])
a.shape
(2, 3)
a.T
array([[0, 3],
[1, 4],
[2, 5]])
a.T.shape
(3, 2)
'Python, Jupyter 🐍 > [python]파이썬 데이터분석' 카테고리의 다른 글
9장 (0) | 2023.04.18 |
---|---|
10장 데이터 집계와 그룹 연산 (0) | 2023.04.17 |
7장 (0) | 2023.04.17 |
[오류] 'jupyter'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는배치 파일이 아닙니다. (0) | 2023.04.09 |
[오류] TypeError: concat() got an unexpected keyword argument 'join_axes' (0) | 2023.04.07 |