NAN/Python

[NumPy_4] 기존 데이터에서 배열 만들기 / 배열 연산

onddd 2021. 6. 30. 22:37
728x90

 

배열 쌓기, 배열 쪼개기

 


기본 형태

 

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가 발생한다.