IT&개발/MachineLearning

왜 Numpy를 배워야 할까? -2 (넘파이 인덱싱, ...)

nimoes._. 2024. 5. 22. 14:00
728x90
반응형

 

2024.05.21 - [PYTHON/MachineLearning] - 왜 Numpy를 배워야 할까? -1

 

왜 Numpy를 배워야 할까? -1 (배열 생성, 차원 변환, ...)

1. Numpy 소개* Numpy 란? 넘파이(Numpy, Numerical Python)는 파이썬에서 과학적 계산을 위한 핵심 라이브러리 중 하나이다. 단순한 문법과 폭넓은 호환성으로 널리 사용되고 있는 파이썬이지만, 대규모

luvtako.tistory.com

- 넘파이 기본 개념과 배열 생성은 이전 글 참고해주세요 :D


1. 넘파이의 ndarray의 데이터 세트 선택하기 - 인덱싱(Indexing)

인덱싱 : 넘파이에서 ndarray 내의 일부 데이터 세트나 특정 데이터만을 선택할 수 있도록 하는 것이다.

 

단일 값 추출 : 원하는 위치의 인덱스 값을 지정하면 해당 위치의 데이터가 반환된다.

슬라이싱(Slicing) : 연속된 인덱스상의 ndarray를 추출하는 방식이다. ':' 기호 사이에 시작 인덱스와 종료 인덱스를 표시하면 시작 인덱스에서 종료 인덱스-1 위치에 있는 데이터의 ndarray를 반환한다.

팬시 인덱싱(Fancy Indexing) : 일정한 인덱싱 집합을 리스트 또는 ndarray 형태로 지정해 해당 위치에 있는 데이터의 ndarray를 반환한다.

불린 인덱싱(Boolean Indexing) : 특정 조건에 해당하는지 여부인 True/False 값 인덱싱 집합을 기반으로 True에 해당하는 인덱스 위치에 있는 데이터의 ndarray를 반환한다.


2. 단일 값 추출

# 1부터 9까지의 1차원 ndarray 생성
array1 = np.arange(1, 10)
print(array1)
# index는 0부터 시작하므로 array1[2]는 3번째 index 위치의 데이터값을 의미
value = array1[2]
print(value)
print(type(value))

 

[output]

[1 2 3 4 5 6 7 8 9]
3
<class 'numpy.int64'>

- 인덱스는 0부터 시작하므로 array1[2]는 3번째 위치의 데이터값을 의미한다.

- array1[2](= value)의 타입은 더 이상 ndarray의 타입이 아니고 ndarray 내의 데이터값을 의미한다.


print(f'맨 뒤의 값 : {array1[-1]}, 맨 뒤에서 두 번째 값 : {array1[-2]}')
# print('맨 뒤의 값 : {}, 맨 뒤에서 두 번째 값 : {}'.format(array1[-1], array1[-2])) 같은 표현

 

[output]

맨 뒤의 값 : 9, 맨 뒤에서 두 번째 값 : 8

- 인덱스에 마이너스 기호를 이용하면 맨 뒤에서부터 데이터를 추출할 수 있다.

- 인덱스 -1은 맨 뒤의 데이터값을 의미하고 -2는 맨 뒤에서 두 번째에 있는 데이터값을 의미한다.


- 단일 인덱스를 이용해 ndarray 내의 데이터값도 수정 가능하다.

array1[0] = 9
array1[8] = 0
print(array1)

 

[output]

[9 2 3 4 5 6 7 8 0]

- 0번 인덱스의 데이터값(1)을 9로 수정

- 8번 인덱스의 데이터값(9)을 0으로 수정


- 2차원의 경우 콤마(,)로 분리된 row와 column 위치의 인덱스를 통해 접근한다. [row, column]

array1d = np.arange(1, 10) # 1차원 배열 생성
array2d = array1d.reshape(3, 3) # reshape를 이용해 array1을 2차원 배열로 변환
print(array2d) # 출력

print(array2d[0, 0])
print(array2d[0, 1])
print(array2d[1, 0])
print(array2d[2, 2])

 

[output]

 [[1 2 3]
 [4 5 6]
 [7 8 9]]
1
2
4
9

- 정확한 표현은 [row = 0, column = 1]이 아닌 [axis 0 = 0, axis 1 = 1]이다.


3. 슬라이싱(Slicing)

- ':' 기호를 이용해 연속한 데이터를 슬라이싱해서 추출할 수 있다.

- 단일 데이터값 추출을 제외하고 슬라이싱, 팬시 인덱싱, 불린 인덱싱으로 추출된 데이터 세트는 모두 ndarray 타입이다.

- ':' 왼쪽에 시작 인덱스와 오른쪽에 종료 인덱스를 표시하면 시작 인덱스에서 종료 인덱스-1의 위치에 있는 데이터의 ndarray를 반환한다.

array1 = np.arange(1, 10)
array3 = array1[0:3]

print(array1)
print(array3)
print(type(array3))

 

[output]

[1 2 3 4 5 6 7 8 9]
[1 2 3]
<class 'numpy.ndarray'>

- 시작, 종료 인덱스는 생략 가능하다.

 

① ':' 기호 앞에 시작 인덱스를 생략하면 자동으로 맨 처음 인덱스인 0으로 간주한다.

② ':' 기호 뒤에 종료 인덱스를 생략하면 자동으로 맨 마지막 인덱스로 간주한다.

③ ':' 기호 앞뒤에 시작과 종료 인덱스를 둘 다 생략하면 맨 처음~맨 마지막 인덱스로 간주한다.

array1 = np.arange(1, 10)

array4 = array1[:3]
print(array4) 

array5 = array1[3:]
print(array5)

array6 = array1[:]
print(array6)

 

[output]

# [:3] - 처음부터 3-1=2번 인덱스까지
[1 2 3]
# [3:] - 3번 인덱스부터 끝까지
[4 5 6 7 8 9]
# [:] - 처음부터 끝까지
[1 2 3 4 5 6 7 8 9]

- 2차원 슬라이싱은 콤마(,)로 row와 column 인덱스를 지칭한다.

- ex) array1[row 시작 인덱스 : row 종료 인덱스, col 시작 인덱스 : col 종료 인덱스]

array1d = np.arange(1, 10)
array2d = array1d.reshape(3, 3)
print(array2d)

print(array2d[0:2, 0:2])
print(array2d[1:3, 0:3])
print(array2d[1:3, :])
print(array2d[:, :])
print(array2d[:2, 1:])
print(array2d[:2, 0])

 

[output]

# array2d
[[1 2 3]
 [4 5 6]
 [7 8 9]]
# array2d[0:2, 0:2]
[[1 2]
 [4 5]]
# array2d[1:3, 0:3]
[[4 5 6]
 [7 8 9]]
# array2d[1:3, :]
[[4 5 6]
 [7 8 9]]
# array2d[:, :]
[[1 2 3]
 [4 5 6]
 [7 8 9]]
# array2d[:2, 1:]
[[2 3]
 [5 6]]
# array2d[:2, 0]
[1 4]

 

 

- 혹시 이해가 잘 안가신다면 그림을 참고해주세요!


- 2차원 ndarray에서 뒤에 오는 인덱스를 없애면 1차원 ndarray를 반환한다.

print(array2d[0])
print(array2d[1])
print(f'array2d[0] shape : {array2d[0].shape} array2d[1] shape : {array2d[1].shape}')

 

[output]

[1 2 3]
[4 5 6]
array2d[0] shape : (3,) array2d[1] shape : (3,)

4. 팬시 인덱싱(Fancy Indexing)

- 팬시 인덱싱은 리스트나 ndarray로 인덱스 집합을 지정하면 해당 위치의 인덱스에 해당하는 ndarray를 반환하는 인덱싱 방식이다.

array1d = np.arange(1, 10)
array2d = array1d.reshape(3, 3)

array3 = array2d[[0, 1], 2]
print(array3.tolist())

array4 = array2d[[0, 1], 0:2]
print(array4.tolist())

array5 = array2d[[0, 1]]
print(array5.tolist())

 

[output]

[3, 6]
[[1, 2], [4, 5]]
[[1, 2, 3], [4, 5, 6]]

5. 불린 인덱싱(Boolean Indexing)

- 불린 인덱싱은 조건 필터링과 검색을 동시에 할 수 있기 때문에 매우 자주 사용되는 인덱싱 방식이다.

- for loop/if else 문보다 훨씬 간단하게 구현 가능하다.

array1d = np.arange(1, 10)
# [ ] 안에 array1d > 5 Boolean indexing을 적용
array3 = array1d[array1d > 5]
print(array3)

 

[output]

[6 7 8 9]

- 넘파이 객체에 조건식을 할당했을 때

array1d > 5

 

[output]

array([False, False, False, False, False,  True,  True,  True,  True])

- 5보다 큰 데이터가 있는 위치는 True, 그렇지 않는 경우는 False 값으로 이뤄진 ndarray 객체가 반환되었다.

 

boolean_indexs = np.array([False, False, False, False, False,  True,  True,  True,  True])
array3 = array1d[boolean_indexs]
print('불린 인덱스로 필터링 결과 :', array3)

 

[output]

불린 인덱스로 필터링 결과 : [6 7 8 9]

- 위와 동일한 불린 ndarray를 만들고 이를 array1d[ ] 내에 인덱스로 입력하면 동일한 데이터 세트가 반환된다.

 

indexs = np.array([5, 6, 7, 8])
array4 = array1d[indexs]
print('일반 인덱스로 필터링 결과 :', array4)

 

[output]

일반 인덱스로 필터링 결과 : [6 7 8 9]

- 직접 인덱스 집합을 만들어 대입한 것과 동일하다.

 

- 불린 인덱싱은 내부적으로 여러 단계를 거쳐서 동작하지만, 코드 자체는 단순히 [ ] 내에 원하는 필터링 조건만 넣으면 해당 조건을 만족하는 ndarray 데이터 세트를 반환하기 때문에 사용자가 내부 로직에 크게 신경 쓰지 않고 쉽게 코딩 가능하다.

 

* 참고 도서

 
파이썬 머신러닝 완벽 가이드
《파이썬 머신러닝 완벽 가이드》는 이론 위주의 머신러닝 책에서 탈피해, 다양한 실전 예제를 직접 구현해 보면서 머신러닝을 체득할 수 있도록 만들었습니다. 캐글과 UCI 머신러닝 리포지토리에서 난이도가 있는 실습 데이터를 기반으로 실전 예제를 구성했고, XGBoost, LightGBM, 스태킹 기법 등 캐글의 많은 데이터 사이언스에서 애용하는 최신 알고리즘과 기법을 상세하게 설명했습니다. 이번 개정2판에서는 최신 사이킷런 버전(1.0.2)을 포함해 책에서 사용되는 모든 라이브러리를 최신 버전으로 업그레이드한 실습 코드를 구현하고, 다양한 유형의 하이퍼파라미터를 가지는 XGBoost나 LightGBM 모델의 최적 하이퍼파라미터 튜닝을 위한 베이지안 최적화 기법 적용 실습을 제공합니다. 또한 머신러닝 관련 데이터 분석에 널리 쓰이는 시각화 라이브러리인 matplotlib과 seaborn의 활용법을 다룬 장을 새롭게 추가했습니다.
저자
권철민
출판
위키북스
출판일
2022.04.21
728x90
반응형