비둘기 둥지

[Python / Numpy]2. Numpy 배열 성질 - 1 본문

데이터 분석/Numpy 공부

[Python / Numpy]2. Numpy 배열 성질 - 1

KimDove 2022. 3. 30. 10:07
728x90

1. 배열의 차원, shape, 크기 

import numpy as np

np.random.seed(0)

## 0 ~ 20까지의 숫자 중에서 10개를 랜덤하게 추출해 만든 1차원 배열
x1 = np.random.randint(20, size = 10)

## 0 ~ 10까지의 숫자 중 랜덤하게 추출해 만든 3x4 2차원 배열
x2 = np.random.randint(10, size = (3, 4))

## 0 ~ 10까지의 숫자 중 랜덤하게 추출해 만든 3x4x5 3차원 배열
x3 = np.random.randint(10, size = (3, 4, 5))

print(f'x3의 차원 : {x3.ndim} \nx3 각 차원의 크기 : {x3.shape}\nx3의 크기 : {x3.size}\nx3의 자료형 : {x3.dtype}')

## 출력 결과
x3의 차원 :         3 
x3 각 차원의 크기 : (3, 4, 5)
x3의 크기 :         60
x3의 자료형 :       int64

2. 배열의 크기를 바이트 단위로 변환

## 각 배열 요소의 크기를 바이트 단위로 반환
print(f'x3 itemsize : {x3.itemsize} bytes')

## 배열 전체 크기를 바이트 단위로 반환
print(f'x3 nbytes :   {x3.nbytes} bytes')

## 출력 결과
x3 itemsize : 8 bytes
x3 nbytes :   480 bytes

3. 배열의 인덱싱, 슬라이싱

3-1. 인덱싱 방법

  1. 단순 인덱싱 : 특정 위치의 단일값 추출  
  2. 팬시 인덱싱 : 단일값대신 인덱스 배열을 반환 -> 복잡한 배열값의 하위 집합에 빠르게 접근 및 수정 가능  
  3. 불리언 인덱싱 : 특정 조건에 해당하는 여부로 True에 해당하는 인덱스 위치의 array를 반환 

## numpy 배열의 인덱싱
## 1. 단순 인덱싱
print(f'Original ndarray x1 :                {x1}')
print(f'Extract 3rd element in ndarray x1 :  {x1[2]}')
print(f'Extract last element in ndarray x1 : {x1[-1]}\n')

## 1-1. 다차원 배열 인덱싱
print(f'Original ndarray x2 :\n{x2}\n')
print(f'Extract (2, 3) element in ndarray x2 :\n{x2[2, 3]}\n')
print(f'Extract (2, 3) element in ndarray x2 (another way) :\n{x2[2][3]}\n')

print(f'Original ndarray x3 :\n{x3}\n')
print(f'Extract (2, 3, 0) element in ndarray x3 :\n{x3[2, 3, 0]}\n')
print(f'Extract (2, 3) element in ndarray x3 (another way) :\n{x3[2][3][0]}')

## 출력 결과
Original ndarray x1 :                [12 15  0  3  3  7  9 19 18  4]
Extract 3rd element in ndarray x1 :  0
Extract last element in ndarray x1 : 4

Original ndarray x2 :
[[7 6 8 8]
 [1 6 7 7]
 [8 1 5 9]]

Extract (2, 3) element in ndarray x2 :
9

Extract (2, 3) element in ndarray x2 (another way) :
9

Original ndarray x3 :
[[[8 9 4 3 0]
  [3 5 0 2 3]
  [8 1 3 3 3]
  [7 0 1 9 9]]
 [[0 4 7 3 2]
  [7 2 0 0 4]
  [5 5 6 8 4]
  [1 4 9 8 1]]
 [[1 7 9 9 3]
  [6 7 2 0 3]
  [5 9 4 4 6]
  [4 4 3 4 4]]]

Extract (2, 3, 0) element in ndarray x3 :
4

Extract (2, 3) element in ndarray x3 (another way) :
4
## 2. 팬시 인덱싱
idxs = [1, 8, 5]
print(f'Original ndarray x1 :                        {x1}')
print(f'Fancy indexing in x1 with index 1, 8 and 5 : {x1[idxs]}\n')


## 2-1. 다차원 배열의 팬시 인덱싱
idxs = [1, 2, 0]
print(f'Original ndarray x2 :\n{x2}\n')

#! 다차원 배열에서 팬시 인덱싱을 적용시 값들의 위치가 변경 됨
print(f'Fancy indexing in x2 with index 1, 2 and 0:\n{x2[idxs]}\n')
print(f'Fancy indexing in x2 :\n{x2[idxs, idxs]}\n')

#! 단순 인덱싱과 팬시 인덱싱을 결합하여 사용할 수 있다.
print(f'Fancy indexing in x2[2] with index 1, 2 and 0 :\n{x2[2, idxs]}')

## 출력 결과
Original ndarray x1 :                        [12 15  0  3  3  7  9 19 18  4]
Fancy indexing in x1 with index 1, 8 and 5 : [15 18  7]

Original ndarray x2 :
[[7 6 8 8]
 [1 6 7 7]
 [8 1 5 9]]

Fancy indexing in x2 with index 1, 2 and 0:
[[1 6 7 7]
 [8 1 5 9]
 [7 6 8 8]]

Fancy indexing in x2 :
[6 5 7]

Fancy indexing in x2[2] with index 1, 2 and 0 :
[1 5 8]
## 3. 불리언 인덱싱
condition = x1%2 == 0
print(f'Original array x1 :                                                      {x1}')
print(f'Mask array condition :                                                   {condition}\n')
print(f'Boolean index in ndarray x1 with mask array condition :                  {x1[condition]}')

## 3-1. 다중 조건 인덱싱
print(f'Boolean index in ndarray x1 with mask array condition or less than 15 :  {x1[(condition) | (x1<15)]}')
print(f'Boolean index in ndarray x1 with mask array condition and less than 15 : {x1[(condition) & (x1<15)]}')

## 출력 결과
Original array x1 :       [12 15  0  3  3  7  9 19 18  4]
Mask array condition :    [ True False  True False False False False False  True  True]

Boolean index in ndarray x1 with mask array condition :                  [12  0 18  4]
Boolean index in ndarray x1 with mask array condition or less than 15 :  [12  0  3  3  7  9 18  4]
Boolean index in ndarray x1 with mask array condition and less than 15 : [12  0  4]

3-2. 슬라이싱

## numpy 배열의 슬라이싱
## 배열[start_idx, end_idx, step_size]
print(f'original array :                            {x1}')
print(f'reversed array :                            {x1[::-1]}')
print(f'array from 0 to 4 :                         {x1[:5]}')
print(f'array from 0 to end_idx with step_size 2 :  {x1[::2]}')
print(f'array from 5 to end_idx with step_size -2 : {x1[5::-2]}')

print(f'original 2 dimension array :\n{x2}')
print(f'\nreversed 2 dimension array :\n{x2[::-1, ::-1]}')
print(f'\n2 columns and 3 rows for 2 dimension array : \n{x2[:2, :3]}')

## 출력 결과
original array :                            [12 15  0  3  3  7  9 19 18  4]
reversed array :                            [ 4 18 19  9  7  3  3  0 15 12]
array from 0 to 4 :                         [12 15  0  3  3]
array from 0 to end_idx with step_size 2 :  [12  0  3  9 18]
array from 5 to end_idx with step_size -2 : [ 7  3 15]

original 2 dimension array :
[[7 6 8 8]
 [1 6 7 7]
 [8 1 5 9]]

reversed 2 dimension array :
[[9 5 1 8]
 [7 7 6 1]
 [8 8 6 7]]

2 columns and 3 rows for 2 dimension array : 
[[7 6 8]
 [1 6 7]]

4. 배열값 변경

## numpy 배열의 값 변경
## 슬라이싱 한 배열의 값을 변경하면, 원본 배열도 값이 변경된다.
x2_ = x2[:2, :2]
print(f'original 2d array :\n{x2} \n\nsliced 2d array : \n{x2_}')
print('\n-------------------------------------------\n')

x2_[0, 0] = 9
print(f'changed original 2d array :\n{x2} \n\nchaned slied 2d array : \n{x2_}')

## 출력 결과
original 2d array :
[[7 6 8 8]
 [1 6 7 7]
 [8 1 5 9]] 

sliced 2d array : 
[[7 6]
 [1 6]]

-------------------------------------------

changed original 2d array :
[[9 6 8 8]
 [1 6 7 7]
 [8 1 5 9]] 

chaned slied 2d array : 
[[9 6]
 [1 6]]
## 복사된 numpy 배열을 슬라이싱 한 배열의 값을 변경해도
## 원본 배열의 값은 변하지 않는다.
x2__ = x2_.copy()
x2__ = x2__[:2, :2]
x2__[0, 0] = 10

print(f'original 2d array :\n{x2} \n\ncopy and sliced 2d array : \n{x2__}')
print('\n-------------------------------------------\n')

x2_[0, 0] = 9
print(f'changed original 2d array :\n{x2} \n\nchaned copy and sliced 2d array : \n{x2__}')

## 출력 결과
original 2d array :
[[9 6 8 8]
 [1 6 7 7]
 [8 1 5 9]] 

copy and sliced 2d array : 
[[10  6]
 [ 1  6]]

-------------------------------------------

changed original 2d array :
[[9 6 8 8]
 [1 6 7 7]
 [8 1 5 9]] 

chaned copy and sliced 2d array : 
[[10  6]
 [ 1  6]]

5. 배열의 재구조화

## numpy 배열의 재구조화
## 재구조화 시키고자 하는 배열의 size와 변경하고자 하는 size가 동일해야한다.
x2_reshaped = x2.reshape(1, 12)

print(f'original 2d array (size : {x2.size}) :  \n{x2}\n')
print(f'\nreshaped 2d array (size : {x2_reshaped.size}) : \n{x2_reshaped}')
print('\n-------------------------------------------\n')

## np.newaixs를 통한 차원 추가
x1_ = x1.copy()
print(f'original 1d array : {x1_}')
print(f'expanded 1d array : {x1_[np.newaxis, :]}')
print(f'expanded 1d array2 : {x1_[:, np.newaxis]}')

## 출력 결과
original 2d array (size : 12) :  
[[9 6 8 8]
 [1 6 7 7]
 [8 1 5 9]]


reshaped 2d array (size : 12) : 
[[9 6 8 8 1 6 7 7 8 1 5 9]]

-------------------------------------------

original 1d array : [12 15  0  3  3  7  9 19 18  4]
expanded 1d array : [[12 15  0  3  3  7  9 19 18  4]]
expanded 1d array2 : [[12]
 [15]
 [ 0]
 [ 3]
 [ 3]
 [ 7]
 [ 9]
 [19]
 [18]
 [ 4]]

6.배열 병합, 분할

6-1. 배열 병합

y1 = np.array([1, 2, 3])
y2 = np.array([3, 2, 1])
y3 = np.array([99, 99, 99])

grid = np.array([[1, 2, 3], [3, 2, 1]])
v, h = np.array([9, 99, 999]), np.array([[1], [11]])

## 같은 차원의 배열 합치기
print(f'concatenated two 1d arrays : \n{np.concatenate([y1, y2])}\n')
print(f'concatenated multiple 1d arrays : \n{np.concatenate([y1, y2, y3])}\n')
print(f'concatenated two 2d arrays : \n{np.concatenate([grid, grid])}\n')

## 혼합된 차원의 배열 합치기
## np.vstack : 수직으로 배열으로 합치기
print(f'vertical stack differences dimension arrays : \n{np.vstack([grid, v])}\n')

## np.hstack : 수평으로 배열으로 합치기
print(f'horizontal stack differences dimension arrays : \n{np.hstack([grid, h])}\n')

## 출력 결과
concatenated two 1d arrays : 
[1 2 3 3 2 1]

concatenated multiple 1d arrays : 
[ 1  2  3  3  2  1 99 99 99]

concatenated two 2d arrays : 
[[1 2 3]
 [3 2 1]
 [1 2 3]
 [3 2 1]]

vertical stack differences dimension arrays : 
[[  1   2   3]
 [  3   2   1]
 [  9  99 999]]

horizontal stack differences dimension arrays : 
[[ 1  2  3  1]
 [ 3  2  1 11]]

6-2. 배열 분할

x = np.arange(8)
x_2d = np.arange(16).reshape(4, 4)

## 배열 분할하기
## np.split을 통해 분할 할 경우엔 (배열의 길이) % (나누고자 하는 길이) = 0이어야 한다.
print(f'original array : {x}')
print(f'splited array :  {np.split(x, 2)}')

print(f'original array : \n{x_2d}\n')
## np.vsplit : 수평으로 분할
upper, lower = np.vsplit(x_2d, [2])
print(f'upper array : \n{upper} \n\nlower array : \n{lower}\n')

## np.hsplit : 수직으로 분할
left, right = np.hsplit(x_2d, [2])
print(f'left array : \n{left} \n\nright array : \n{right}')

## 출력 결과
original array : [0 1 2 3 4 5 6 7]
splited array :  [array([0, 1, 2, 3]), array([4, 5, 6, 7])]
original array : 
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

upper array : 
[[0 1 2 3]
 [4 5 6 7]] 

lower array : 
[[ 8  9 10 11]
 [12 13 14 15]]

left array : 
[[ 0  1]
 [ 4  5]
 [ 8  9]
 [12 13]] 

right array : 
[[ 2  3]
 [ 6  7]
 [10 11]
 [14 15]]

99. 참고 자료

  • O'REILLY | 제이크 밴더 플래스 저 / 위키북스 김정인 역 - 파이썬 데이터 사이언스 핸드북
  • Grace's Tech Blog | 2. numpy - ndarray 인덱싱 & 슬라이싱 이해
 

2. numpy - ndarray 인덱싱 & 슬라이싱 이해

2. ndarray 인덱싱 & 슬라이싱 이해하기¶ 1) 인덱싱이란 :¶ 파이썬 리스트와 동일한 개념으로 사용되며 , 를 사용하여 각 차원의 인덱스에 접근 가능 ndarray에서 원하는 데이터세트를 선택하는데 매

libertegrace.tistory.com


전체 코드

 

GitHub - EvoDmiK/TIL: Today I Learn

Today I Learn. Contribute to EvoDmiK/TIL development by creating an account on GitHub.

github.com


부탁의 말씀

개인적으로 공부하는 과정에서 오류가 있을 수 있으니, 오류가 있는 부분은 댓글로 정정 부탁드립니다.


 

728x90

'데이터 분석 > Numpy 공부' 카테고리의 다른 글

[Python / Numpy] 1. 여러 배열 만들기  (0) 2022.03.30
Comments