250801 [ Day 20 ] - NumPy (2)

TaeHyun·2025년 8월 1일

TIL

목록 보기
20/185

시작하며

어제에 이어 NumPy의 기본 사용법과 인덱싱, 슬라이싱에 대해 배웠다. 인덱싱과 슬라이싱은 기본적으로 리스트의 인덱싱, 슬라이싱과 비슷했지만 다차원 배열에 유용한 추가 기능이 많이 있었다.

인덱싱과 슬라이싱

  • 파이썬 시퀀스와 동일하게 0부터 시작하는 인덱스 사용
    • 기본적인 문법은 동일
    • 다차원 인덱싱과 조건 기반 요소 선택 등의 편의 기능을 제공
    • 파이썬 시퀀스보다 더 빠른 연산 수행 가능

인덱싱

  • 1차원 인덱싱은 파이썬 리스트 인덱싱과 동일
a = np.array([1,2,3,4,5])
print(a[1]) # 2
print(a[-1]) # 5
  • 다차원 배열의 인덱싱
# 파이썬 리스트
matrix = [[1,2,3], [4,5,6]]
print("파이썬 인덱싱 :", matrix[1][1])
# 파이썬 인덱싱 : 5

# NumPy 배열
a2 = np.array([[1,2,3], [4,5,6]])
print("넘파이 인덱싱 :", a2[1, 1])
# 넘파이 인덱싱 : 5
a3 = np.arange(24).reshape(2,3,4)
print(a3)
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]

#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

print("17 확인", a3[1,1,1])
print("11 확인", a3[0,2,3])
# 17 확인 17
# 11 확인 11

슬라이싱

  • 리스트 슬라이싱과 동일한 문법을 사용하지만, 결과가 새로운 리스트 반환이 아닌 뷰(View)이다.

뷰(View)

원본 데이터의 메모리를 공유하기에 슬라이스 결과를 수정하면 원본 배열도 변경

  • 1차원 슬라이싱 = 리스트 슬라이싱과 동일
a1 = np.array([1,2,3,4,5])

print(a1[1:3]) # [2 3]
print(a1[2:]) # [3 4 5]
print(a1[:2]) # [1 2]
print(a1[::2]) # [1 3 5]
print(a1[::-1]) # [5 4 3 2 1]
  • 2차원 슬라이싱 = arr[행 슬라이스, 열 슬라이스]
a2 = np.arange(1, 21).reshape(4,5)
print(a2)
# [[ 1  2  3  4  5]
#  [ 6  7  8  9 10]
#  [11 12 13 14 15]
#  [16 17 18 19 20]]

# 행 슬라이싱 = 2차원 슬라이싱
print(a2[0, :])
# [1 2 3 4 5]
print(a2[1])
# [ 6  7  8  9 10]
print(a2[1:3])
# [[ 6  7  8  9 10]
#  [11 12 13 14 15]]
print(a2[2:])
# [[11 12 13 14 15]
#  [16 17 18 19 20]]

# 열 슬라이싱 = 1차원 슬라이싱
print(a2[:, 2])
# [ 3  8 13 18]
print(a2[:, -1])
# [ 5 10 15 20]
print(a2[:, 1:3])
# [[ 2  3]
#  [ 7  8]
#  [12 13]
#  [17 18]]

# 행과 열 슬라이싱
print(a2[1:3, 2:4])
# [[ 8  9]
#  [13 14]]
print(a2[2:, 3:])
# [[14 15]
#  [19 20]]
print(a2[::2, ::2])
# [[ 1  3  5]
#  [11 13 15]]
  • 다차원 슬라이싱 = arr[3차원 슬라이스, 2차원 슬라이스, 1차원 슬라이스]
a3 = np.arange(36).reshape(3,3,4)
print(a3)
# [[[ 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 25 26 27]
#   [28 29 30 31]
#   [32 33 34 35]]]

print(a3[1, 1, 1:3])
# [17 18]

배열의 복사(Copy)와 참조(View)

  1. 얕은 복사(Shallow Copy) : 복사본이 원본과 메모리를 공유 -> 변경사항이 서로에게 영향을 줌
a1 = np.array([1,2,3])
a1_copied = a1.view()
a1_copied[1] = 10
print("원본", a1) # 원본 [ 1 10  3]
print("복사본", a1_copied) # 복사본 [ 1 10  3]
  1. 깊은 복사(Deep Copy) : 복사본이 원본과 독립적으로 복사됨 -> 서로 영향을 주지 않음
a2 = np.array([1,2,3])
a2_copied = a2.copy()
a2_copied[1] = 10
print("원본", a2) # 원본 [ 1 2  3]
print("복사본", a2_copied) # 복사본 [ 1 10  3]

Fancy Indexing

  • 정수 배열을 사용하여 여러 인덱스로 여러 요소를 한번에 선택
af = np.arange(1,21)
print(af)
# [ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20]

print(af[[4,7,11]])
# [ 5  8 12]
  • 2차원 배열에서의 Fancy Indexing
af2 = np.arange(1, 21).reshape(4,5)
print(af2)
# [[ 1  2  3  4  5]
#  [ 6  7  8  9 10]
#  [11 12 13 14 15]
#  [16 17 18 19 20]]

print(af2[[1,3],[2,4]])
# [ 8 20]
  • Fancy Indexing을 사용해서 순서 바꾸기 가능
arr = np.arange(1, 26).reshape(5, 5)
print(arr, "\n")
# [[ 1  2  3  4  5]
#  [ 6  7  8  9 10]
#  [11 12 13 14 15]
#  [16 17 18 19 20]
#  [21 22 23 24 25]] 

new_arr = arr[[1,3]]
print(new_arr[:, [4,0,2]])
# [[10  6  8]
#  [20 16 18]]

Boolean Indexing

ab = np.linspace(10,100,10)
print(ab)
# [ 10.  20.  30.  40.  50.  60.  70.  80.  90. 100.]
print(ab[ab > 40])
# [ 50.  60.  70.  80.  90. 100.]

Boolean Masking

ab2 = np.arange(0,21)
print(ab2)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20]
mask = ab2 % 2 == 0
print(mask)
# [ True False  True False  True False  True False  True False  True False
#   True False  True False  True False  True False  True]
print(ab2[mask])
# [ 0  2  4  6  8 10 12 14 16 18 20] 

마치며

오늘은 주로 배열을 생성한 후 생성된 배열로 여러 인덱싱과 슬라이싱을 하는 연습을 많이 했다. NumPy의 기본기는 앞으로를 생각하면 지금 충분히 많은 문제들을 풀어보며 익숙해지는 것이 좋을 것 같아서 주말 동안 많은 NumPy 관련 문제들을 풀어봐야겠다.

NOTION

MY NOTION (NumPy. 01)

profile
Hello I'm TaeHyunAn, Currently Studying Data Analysis

0개의 댓글