[NumPy_4] 기존 데이터에서 배열 만들기 / 배열 연산
배열 쌓기, 배열 쪼개기
기본 형태
np.vstack(tuple) : 두 배열을 세로로 쌓아 하나의 배열을 만든다.
np.hstack(tuple) : 두 배열을 가로로 쌓아 하나의 배열을 만든다.
- np.vstack(arr1, arr2)의 형태로 array가 튜플 타입으로 들어간다.
- 첫 번째 축을 제외하고 모두 같은 모양이어야 하고, 1차원 배열은 길이가 같아야 한다.
arr1 = np.array([[1, 1],[2, 2]])
arr2 = np.array([[3, 3],[4, 4]])
arr_vstack = np.vstack((arr1, arr2))
print(arr_vstack)
[[1 1]
[2 2]
[3 3]
[4 4]]
arr_hstack = np.hstack((arr1, arr2))
print(arr_hstack)
print(arr_hstack)
[[1 1 3 3]
[2 2 4 4]]
기본 형태
np.vsplit(arr, indices_or_sections) : 하나의 배열을 세로로 쪼개 n개의 배열을 만든다.
np.hsplit(arr, indices_or_sections) : 하나의 배열을 가로로 쪼개 n개의 배열을 만든다.
- arr1, arr2, arr3 = np.vsplit(array,3)의 형태로 사용한다.
- v, h에 따라 행, 열 방향을 기준
- indices_or_sections : int 또는 나누고 싶은 행을 입력하여 사용한다.
행방 향 나누기
arr = np.arange(1,25).reshape(6, 4)
print(arr)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]
arr1,arr2,arr3 = np.vsplit(arr, 3)
print(arr1)
print()
print(arr2)
print()
print(arr3)
[[1 2 3 4]
[5 6 7 8]]
[[ 9 10 11 12]
[13 14 15 16]]
[[17 18 19 20]
[21 22 23 24]]
# 나누고싶은 행을 선택한 경우
arr_row1, arr_row2, arr_row3 = np.vsplit(arr,(3,5))
print(arr_row1)
print()
print(arr_row2)
print()
print(arr_row3)
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[13 14 15 16]
[17 18 19 20]]
[[21 22 23 24]]
열 방향 나누기
arr = np.arange(1,25).reshape(2,12)
print(arr)
[[ 1 2 3 4 5 6 7 8 9 10 11 12]
[13 14 15 16 17 18 19 20 21 22 23 24]]
arr1,arr2,arr3 = np.hsplit(arr, 3)
print(arr1)
print()
print(arr2)
print()
print(arr3)
[[ 1 2 3 4]
[13 14 15 16]]
[[ 5 6 7 8]
[17 18 19 20]]
[[ 9 10 11 12]
[21 22 23 24]]
vsplit()와 마찬가지로 나누고 싶은 열을 지정하여 나눌 수 있다.
깊은 복사, 얕은 복사
예를 들어 arr1 = ([1,2,3,4])라는 데이터를 가지고 있다고 하자,
이를 arr2 = arr1으로 표현하면 arr2와 arr1은 동일한 객체를 가지고 있다고 볼 수 있는데
이는 arr1와 arr2가 가리키는 주소 값이 같을 뿐 복사가 되었다고 할 수 없다.
주소가 같기 때문에 arr1의 값을 바꿨을 때 arr2의 값 역시 함께 변경된다.
import numpy as np
arr1 = np.array([1,2,3,4])
arr2 = arr1
print(arr1 in arr2)
True
얕은 복사
얕은 복사 방식으로는 view 메서드가 있는데 이 같은 경우 동일한 데이터를 보는 새 배열 객체를 만든다.
다시 말해 주소는 다르지만 같은 데이터를 보고 있다는 말이기 때문에,
이 역시 a값을 바꾸면 b값도 변경되어 얕은 복사라고 표현한다.
rr1 = np.array([0,1,2,3,4])
arr2 = arr1.view()
print(arr1 is arr2)
arr1[1] = 99
print(arr2)
print(id(arr1))
print(id(arr2))
False
[ 0 99 2 3 4]
140260203212192
140260203342144
이처럼 값은 변동이 있지만 전혀 다른 주소 값을 가지고 있다.
깊은 복사
copy 메서드는 배열과 데이터의 완전한 복사본을 만들기 때문에 a값을 바꾼다 하더라도 b값은 변동이 없다.
arr1 = np.array([1,2,3,4,5])
arr2 = arr1.copy()
print(arr1 is arr2)
False
arr1[1]=99
print(arr2)
print(id(arr1))
print(id(arr2))
[1 2 3 4 5]
140260203023376
140260203020336
배열 연산
numpy에서는 배 열간 기본적인 사칙 연산뿐만 아니라 평균, 표준 편차 등 다양한 수 계산을 도와주는데,
사용법은 비교적 단순하지만 행렬의 구분을 확실하게 할 줄 알아야 유용하게 사용할 수 있다.
사칙 연산
arr1 = np.array([1,2])
arr2 = np.ones(2, dtype=int)
print(arr1+arr2)
[2 3]
print(arr1-arr2)
[0 1]
print(arr1*arr2)
[1 2]
print(arr1/arr2)
[1. 2.]
여기서 곱셈은 원소끼리의 곱이다.
sum( )
배열을 이루고 있는 원소의 합을 구할때 sum( )을 사용하고, 1차원 이상의 높은 차원을 가진 배열에서도 모두 작동하는데
축 기준을 어디로 잡느냐에 따라 계산 값이 달라진다.
arr = np.array([1,2,3,4])
print(arr.sum())
10
arr = np.array([[1,1],[2,2]])
print(arr.sum(axis=1))
print(arr.sum(axis=0))
[2 4]
[3 3]
max( ), min( )
이름 그대로 주어진 축에 따라 최댓값, 최솟값을 반환한다.
arr = np.array([[4,2,5,6,2,6],
[9,54,3,8,4,67],
[14,36,58,547,32,7]])
print(arr.max(axis=0)) # 행(세로) 기준
print(arr.max(axis=1)) # 열(가로) 기준
[ 14 54 58 547 32 67]
[ 6 67 547]
print(arr.max()) # 디폴트 전체 기준 가장 큰 값
547
arr = np.array([[4,2,5,6,2,6],
[9,54,3,8,4,67],
[14,36,58,547,32,7]])
print(arr.min(axis=0)) # 행(세로) 기준
print(arr.min(axis=1)) # 열(가로) 기준
print(arr.min()) # 디폴트 전체 기준 가장 작은 값
[4 2 3 6 2 6]
[2 3 7]
2
평균 구하기
mean( ) 메소드는 지정된 축을 따라 산술 평균을 구한다.
arr = np.array([[4,2,5,6,2,6],
[9,54,3,8,4,67],
[14,36,58,547,32,7]])
print(arr.mean(axis=0)) # 행(세로) 기준
print(arr.mean(axis=1)) # 열(가로) 기준
print(arr.mean()) # 디폴트 전체 값 평균
[ 9. 30.66666667 22. 187. 12.66666667
26.66666667]
[ 4.16666667 24.16666667 115.66666667]
48.0
표준 편차
std ( ) 메소드는 지정된 축을 따라 표준 편차 계산
arr = np.array([[4,2,5,6,2,6],
[9,54,3,8,4,67],
[14,36,58,547,32,7]])
print(arr.std(axis=0)) # 행(세로) 기준
print(arr.std(axis=1)) # 열(가로) 기준
print(arr.std()) # 디폴트 전체 표준 편차
[ 4.0824829 21.56128217 25.46893533 254.55975068 13.69509239
28.52289529]
[ 1.67497927 26.04749935 193.59120733]
122.78300642461345
배열의 곱
prod( ) 주어진 축의 배열 요소 곱 반환
arr = np.array([[4,2,5,6,2,6],
[9,54,3,8,4,67],
[14,36,58,547,32,7]])
print(arr.prod(axis=0)) # 행(세로) 기준
print(arr.prod(axis=1)) # 열(가로) 기준
print(arr.prod()) # 디폴트 전체 배열 곱
[ 504 3888 870 26256 256 2814]
[ 2880 3125952 3581738496]
-4648021416080310272
배열 간 내적 구하기
dot( )는 두 배열의 내적을 구해준다.
arr1 = np.eye(2)
arr2 = np.ones((2, 2)) * 2
print(arr1)
print(arr2)
print()
print(arr1.dot(arr2))
[[1. 0.]
[0. 1.]]
[[2. 2.]
[2. 2.]]
[[2. 2.]
[2. 2.]]
dot는 연결해서 사용할 수 있다는 특징을 가지고 있다.
print(arr1.dot(arr2).dot(arr2))
[[8. 8.]
[8. 8.]]
배열 간 행렬 곱
np.matmul( ) 함수는 두 배열의 행렬 곱을 구해준다.
arr1 = np.array([[1, 0],[0,1]])
arr2 = np.array([[4, 1],[2,2]])
print(np.matmul(arr1,arr2))
[[4 1]
[2 2]]
알고 가기
numpy의 특징인 브로드캐스트는 배열과 배열의 연산 과정에서 shape의 모양이 다르더라도
연산을 위해 배열의 모양을 자동으로 맞춰 주는 기능을 말한다.
이 기능이 있기 때문에 shape가 다른 배열의 연산, 배열과 스칼라의 연산이 가능하다.
arr = np.array([1.0, 2.0])
print(arr * 1.6)
[1.6 3.2]
위의 곱셈처럼 arr를 이루고 있는 요소는 두 개지만 곱셈을 하기 위해 1.6 요소 하나를 자동으로 추가하여
배열의 크기를 맞춰 준다 이해하면 되겠다.
이런 개념으로 shape이 다른 배열 간의 연산도 가능하지만,
이 경우 shape이 같거나 차원 중 값이 1인 것이 존재해야만 가능하다. 이 조건이 충족되지 않는다면
Value Error가 발생한다.
