[Python] 데이터 사이언스 스쿨 - 3.1 넘파이 배열
Updated:
데이터 사이언스 스쿨 자료를 토대로 공부한 내용입니다.
실습과정에서 필요에 따라 내용의 누락 및 추가, 수정사항이 있습니다.
3.1 넘파이 배열
1차원 배열 생성
import numpy as np
k1 = np.array([0,1,2,3,4,5,6,7,8,9])
print(k1)
type(k1)
[0 1 2 3 4 5 6 7 8 9]
numpy.ndarray
-
numpy
패키지는 파이썬에서 특히 데이터를 다룬다면 필수적인 패키지이다. -
np.array()
로 넘파이 배열을 생성할 수 있으며 type은 numpy.ndarray이다.
벡터화 연산
# 리스트
data = [0,1,2,3,4,5,6,7,8,9]
# 베열
x = np.array(data)
# 리스트와 달리 배열은 벡터화 연산이 가능
print(data * 2)
print(x * 2)
# 리스트로 같은 연산
lst = []
for i in data:
lst.append(i*2)
print(lst)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[ 0 2 4 6 8 10 12 14 16 18]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
-
넘파이 배열의 큰 특징 중 하나는 벡터화 연산이 가능하다는 점이다.
-
위 예제에서 리스트와 넘파이 배열을 생성한 후 똑같이 2를 곱하였을 때 리스트는 같은 데이터가 2배로 늘어났다.
-
반면에 넘파이 배열은 각 숫자에 2가 곱해진 값으로 나타난다.
-
리스트로 같은 결과를 출력하려면 for문을 이용해서 출력하여는데 그에 비해 넘파이 배열은 훨씬 편하게 작업할 수 있다.
2차원 배열
# 2 x 3 행렬
m1 = np.array( [ [0,1,2],
[3,4,5] ])
print(m1)
# 행의 갯수
print("행의 갯수:", len(m1))
# 열의 갯수
print("열의 갯수:", len(m1[0]))
[[0 1 2]
[3 4 5]]
행의 갯수: 2
열의 갯수: 3
-
넘파이는 1차원 배열외에도 2차원, 3차원 등 다차원 배열 생성이 가능하다.
-
바깥쪽 리스트의 길이가 행의 갯수가 되며, 안쪽 리스트의 길이는 열의 갯수가 된다.
연습문제 1
넘파이를 사용하여 다음과 같은 행렬을 만든다.
10 20 30 40
50 60 70 80
# 2 x 4 행렬
k2 = np.array( [[10,20,30,40],
[50,60,70,80]])
print(k2)
[[10 20 30 40]
[50 60 70 80]]
3차원 배열
# 2 x 3 x 4 행렬
k3 = np.array([[[1,2,3,4],
[5,6,7,8],
[10,11,12,13]],
[[14,15,16,17],
[18,19,20,21],
[22,23,24,25]]])
print(k3)
print("-"*20)
# 차원, 행, 열의 갯수
print("차원:", len(k3))
print("행:", len(k3[0]))
print("열:", len(k3[0][0]))
[[[ 1 2 3 4]
[ 5 6 7 8]
[10 11 12 13]]
[[14 15 16 17]
[18 19 20 21]
[22 23 24 25]]]
--------------------
차원: 2
행: 3
열: 4
-
3 x 4로 이루어진 2개의 행렬을 묶어 2 x 3 x 4 행렬을 만들었다.
-
3차원 배열은 (차원) x (행) x (열)로 구성된다.
-
차원은 깊이라는 표현으로도 사용한다.
배열의 차원과 크기
# 1차원
a1 = np.array([1,2,3])
# 2차원
a2 = np.array([[0,1,2],
[3,4,5]])
# 3차원
a3 = np.array([[[1,2,3,4],
[5,6,7,8],
[10,11,12,13]],
[[14,15,16,17],
[18,19,20,21],
[22,23,24,25]]])
print("차원:", a1.ndim, "크기:", a1.shape)
print("차원:", a2.ndim, "크기:", a2.shape)
print("차원:", a3.ndim, "크기:", a3.shape)
차원: 1 크기: (3,)
차원: 2 크기: (2, 3)
차원: 3 크기: (2, 3, 4)
-
앞서
len()
으로 하나씩 차원, 행, 열의 갯수를 구하였다. -
ndim
속성을 사용하면 배열의 차원을 알 수 있고,shape
속성을 사용하면 크기를 알 수 있다.
배열의 인덱싱
1차원 배열의 인덱싱
b1 = np.array([0,1,2,3,4])
print(b1[1])
print(b1[-1])
1
4
- 1차원 배열의 인덱싱은 리스트와 동일하다.
2차원 배열의 인덱싱
b2 = np.array([[0,1,2],
[3,4,5]])
print(b2[0,0])
print(b2[-1,-1])
0
5
- 2차원 배열의 인덱싱은 콤마를 이용해서 앞에는 행, 뒤에는 열에 대해 인덱싱한다.
3차원 배열의 인덱싱
b3 = np.array([[[1,2,3,4],
[5,6,7,8],
[10,11,12,13]],
[[14,15,16,17],
[18,19,20,21],
[22,23,24,25]]])
print(b3[1,1,1])
print(b3[1,2,3])
19
25
- 3차원 배열의 인덱싱은 2차원 배열의 인덱싱에서 콤마를 추가해 각각 차원, 행, 열에 대해 인덱싱한다.
배열 슬라이싱
k = np.array([[0,1,2,3],
[4,5,6,7]])
# 두번째 행 전체
print(k[1, :])
# 첫번째 열 전체
print(k[:,0])
# 첫번째 행의 두번째 열부터 끝까지
print(k[0,1:])
# 처음 2개의 행과 열
print(k[:2, :2])
[4 5 6 7]
[0 4]
[1 2 3]
[[0 1]
[4 5]]
- 배열의 슬라이싱은 2차원 배열 기준으로 [행 슬라이싱, 열 슬라이싱] 방식으로 수행한다.
연습문제 2
다음 행렬과 같은 행렬이 있다.
m = np.array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
-
이 행렬에서 값 7 을 인덱싱한다.
-
이 행렬에서 값 14 을 인덱싱한다.
-
이 행렬에서 배열 [6, 7] 을 슬라이싱한다.
-
이 행렬에서 배열 [7, 12] 을 슬라이싱한다.
-
이 행렬에서 배열 [[3, 4], [8, 9]] 을 슬라이싱한다.
m = np.array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
print(m[1,2])
print(m[-1,-1])
print(m[1,1:3])
print(m[1:,2])
print(m[:2,-2:])
7
14
[6 7]
[ 7 12]
[[3 4]
[8 9]]
배열 인덱싱 (fancy indexing)
넘파이 배열의 강력한 기능 중 하나는 팬시 인덱싱(fancy indexing)이라고도 부르는 배열 인덱싱(array indexing) 방법이다.
단순하게 생각하면 배열에 다른 배열을 위치 정보로 사용하는 방법이다.
배열 인덱싱은 Boolean 배열과 정수 배열을 위치 정보로 사용 가능하다.
-
Boolean 배열을 위치 정보로 사용할 경우 Boolean 배열과 원래 배열의 크기가 같아야한다.
-
정수 배열을 위치 정보로 사용할 경우 원래 배열과 크기가 달라도 상관없다.
불린 배열 인덱싱
a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
idx = np.array([True, False, True, False, True, False, True, False, True, False])
a[idx]
array([0, 2, 4, 6, 8])
# 위 과정을 단순하게
a[a % 2 == 0]
array([0, 2, 4, 6, 8])
- 위 예시와 같이 True, False로 나타나는 Boolean 배열을 이용하여 원래 배열에서 True인 배열만 추출할 수 있다.
정수 배열 인덱싱
a = np.array([11, 22, 33, 44, 55, 66, 77, 88, 99])
idx = np.array([0, 2, 4, 6, 8]) # 홀수 원소
a[idx]
array([11, 33, 55, 77, 99])
- 정수 배열 인덱싱은 원하는 위치 정보(인덱스 정보) 배열을 입력하여 원래 배열에서 추출할 수 있다.
a = np.array([11, 22, 33, 44, 55, 66, 77, 88, 99])
idx = np.array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2])
a[idx]
array([11, 11, 11, 11, 11, 11, 22, 22, 22, 22, 22, 33, 33, 33, 33, 33])
- 다음과 같이 정수 배열의 크기가 원래 배열의 크기보다 커도 상관없으며 해당 인덱스를 중복해서 추출한다.
다차원 배열
# 2차원 배열
k = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
# 모든 행과 2,3열
print(k[:, [False, True, True, False]])
# 열 순서 바꿔 출력
print(k[:,[3,1,2,0]])
[[ 2 3]
[ 6 7]
[10 11]]
[[ 4 2 3 1]
[ 8 6 7 5]
[12 10 11 9]]
- 배열 인덱싱은 1차원 배열뿐 아니라 다차원 배열에서도 똑같이 적용 가능하다.
연습문제 3
다음 행렬과 같은 배열이 있다.
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
-
이 배열에서 3의 배수를 찾아라.
-
이 배열에서 4로 나누면 1이 남는 수를 찾아라.
-
이 배열에서 3으로 나누면 나누어지고 4로 나누면 1이 남는 수를 찾아라.
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
# 3의 배수
print(x[x % 3 == 0])
# 4의 배수 + 1
print(x[x % 4 == 1])
# 3의 배수 & 4의 배수 + 1
print( x[ (x % 3 == 0) & (x % 4 == 1) ] )
[ 3 6 9 12 15 18]
[ 1 5 9 13 17]
[9]
- 한 가지 자주하던 실수가 여러 조건을 and, or로 결합해서 줄 떄 각 조건은 반드시 소괄호( )로 묶어야 한다.
Leave a comment