지난 3부에서는 NumPy 배열을 대상으로 계산하는 방법을 공부했습니다.
arr + 10
arr * 10
처럼 배열 전체를 한 번에 계산할 수도 있었고,
서로 shape이 다른 배열도 일정한 규칙을 만족하면 브로드캐스팅을 통해 계산할 수 있다는 것도 알아봤습니다.
이번에는 조금 다른 주제입니다.
바로,
배열 안에서 내가 원하는 데이터만 어떻게 꺼낼 것인가?
입니다.
생각해보면 실제 데이터 분석에서는 데이터를 만드는 것보다 원하는 데이터를 찾아내는 작업을 훨씬 자주 하게 될 것 같습니다.
예를 들어,
전체 고객 데이터 중 30대 고객만 찾기
주가 데이터에서 거래량이 일정 수준 이상인 날짜만 찾기
센서 데이터에서 비정상적인 값만 찾기
이미지 배열에서 특정 영역만 잘라내기
같은 작업들입니다.
NumPy에서는 이런 작업을 위해 여러 가지 방법을 제공합니다.
이번 글에서는
인덱싱
슬라이싱
Boolean Indexing
Fancy Indexing
Transpose
를 하나씩 정리해보겠습니다.
1. 먼저 배열을 하나 만들어보겠습니다
이번에는 1부터 6까지의 숫자를 이용해서 2차원 배열을 만들어보겠습니다.
import numpy as np
arr = np.arange(1, 7).reshape(2, 3)
결과는 다음과 같습니다.
[
[1, 2, 3],
[4, 5, 6]
]
shape을 확인하면
arr.shape
결과는
(2, 3)
입니다.
즉,
2개의 행
3개의 열
을 가진 2차원 배열입니다.
이제 이 배열에서 원하는 데이터를 하나씩 꺼내보겠습니다.
2. 인덱싱(Indexing)이란 무엇일까요?
파이썬 리스트를 사용할 때 이미 인덱싱을 사용해봤습니다.
numbers = [10, 20, 30]
numbers[0]
결과는
10
입니다.
NumPy도 기본적인 개념은 같습니다.
arr[0]
이라고 하면 첫 번째 데이터를 가져옵니다.
현재 배열이
[
[1, 2, 3],
[4, 5, 6]
]
이므로
arr[0]
결과는
[1, 2, 3]
입니다.
즉 2차원 배열에서 첫 번째 행 하나를 가져온 것입니다.
3. NumPy도 인덱스는 0부터 시작합니다
이 부분은 일반적인 파이썬과 같습니다.
첫 번째 → 0
두 번째 → 1
세 번째 → 2
따라서
arr[0]
은 첫 번째 행,
arr[1]
은 두 번째 행이 됩니다.
처음 배울 때는
“첫 번째인데 왜 1이 아니라 0이지?”
라고 생각하기 쉬운데, 파이썬과 NumPy 모두 0부터 시작한다고 기억하면 됩니다.
4. 음수 인덱스도 사용할 수 있습니다
파이썬 리스트와 마찬가지로 NumPy에서도 음수 인덱스를 사용할 수 있습니다.
-1 → 마지막
-2 → 뒤에서 두 번째
예를 들어
arr[0][-1]
이라고 하면
먼저
arr[0]
에서
[1, 2, 3]
을 가져오고,
그중 마지막 값인
3
을 가져오게 됩니다.
즉 결과는
3
입니다.
5. NumPy에서는 좌표처럼 접근할 수도 있습니다
앞에서
arr[0][-1]
처럼 두 번 인덱싱했습니다.
그런데 NumPy에서는 다음처럼 작성할 수도 있습니다.
arr[0, -1]
결과는 동일합니다.
3
개인적으로 NumPy에서는 이 방식이 조금 더 직관적으로 느껴졌습니다.
왜냐하면
arr[행, 열]
처럼 좌표를 지정하는 느낌이 들기 때문입니다.
예를 들어
arr[1, 2]
라면
두 번째 행
세 번째 열
을 의미합니다.
현재 배열에서는
6
이 됩니다.
6. 인덱싱을 하면 차원이 줄어들 수 있습니다
이 부분은 알아둘 필요가 있습니다.
현재 배열은 2차원입니다.
arr.ndim
결과는
2
입니다.
그런데
arr[0]
으로 첫 번째 행을 가져오면 결과는
[1, 2, 3]
입니다.
이 배열의 차원을 확인하면
arr[0].ndim
결과는
1
입니다.
즉,
2차원 배열
↓
한 행 인덱싱
↓
1차원 배열
이 되었습니다.
여기서 다시
arr[0][0]
처럼 값 하나를 가져오면 배열이 아니라 스칼라 값이 됩니다.
2차원
↓
1차원
↓
스칼라
이런 식으로 차원이 줄어들 수 있습니다.
이 부분이 나중에 shape을 다룰 때 꽤 중요할 것 같습니다.
7. 슬라이싱(Slicing)이란 무엇일까요?
인덱싱이 특정 위치의 데이터를 하나 선택하는 느낌이라면,
슬라이싱은 일정한 구간을 잘라내는 것에 가깝습니다.
기본 문법은 파이썬 리스트와 같습니다.
배열[시작:끝:간격]
예를 들어
arr[:]
이라고 하면 처음부터 끝까지 가져옵니다.
즉 배열 전체가 나옵니다.
8. 2차원에서는 각 축마다 슬라이싱할 수 있습니다
2차원 배열에서는 쉼표를 기준으로 각 차원을 따로 지정할 수 있습니다.
arr[:, :]
이 의미를 풀어보면
첫 번째 : → 모든 행
두 번째 : → 모든 열
입니다.
즉 배열 전체를 가져옵니다.
[
[1, 2, 3],
[4, 5, 6]
]
처음에는
arr[:]
와
arr[:, :]
가 왜 둘 다 존재하는지 조금 헷갈렸습니다.
2차원 배열에서는
arr[:, :]
처럼 작성하면 행과 열을 각각 어떻게 선택하는지 명확하게 표현할 수 있다고 이해했습니다.
9. 특정 행이나 열만 선택할 수도 있습니다
예를 들어 첫 번째 행만 가져오고 싶다면
arr[:1, :]
처럼 사용할 수 있습니다.
현재 배열에서는
[
[1, 2, 3]
]
이 나옵니다.
반대로 첫 번째 열을 모두 가져오고 싶다면
arr[:, 0]
이라고 할 수 있습니다.
결과는
[1, 4]
입니다.
여기서 재미있는 점은
arr[:, 0]
에서
:
는 슬라이싱이고,
0
은 인덱싱이라는 점입니다.
즉 NumPy에서는 인덱싱과 슬라이싱을 섞어서 사용할 수 있습니다.
10. 인덱싱과 슬라이싱의 차이
현재 단계에서는 다음처럼 이해하려고 합니다.
인덱싱
→ 특정 위치 선택
→ 차원이 줄어들 수 있음
슬라이싱
→ 범위 선택
→ 차원을 유지할 수 있음
예를 들어
arr[0]
은 첫 번째 행을 인덱싱합니다.
반면
arr[0:1]
은 첫 번째 행 구간을 슬라이싱합니다.
겉으로 보면 비슷한 데이터가 나오지만 shape은 달라질 수 있습니다.
이 차이는 머신러닝이나 딥러닝을 하다 보면 꽤 중요할 것 같습니다.
11. Boolean Indexing — 조건에 맞는 데이터만 골라내기
이번 부분은 개인적으로 굉장히 중요해 보였습니다.
Boolean Indexing입니다.
지난 글에서 이런 연산을 했습니다.
arr >= 0
배열 안의 각 값이 조건을 만족하는지를 검사해서
True
False
로 구성된 Boolean 배열이 만들어졌습니다.
이 Boolean 결과를 그대로 데이터 선택에 사용할 수 있습니다.
12. 랜덤 데이터를 하나 만들어보겠습니다
arr = np.random.randn(4, 10)
shape을 확인하면
(4, 10)
입니다.
평균이 0이고 표준편차가 1인 정규분포에서 만들어진 랜덤 값이므로 양수와 음수가 섞여 있을 수 있습니다.
예를 들어 대략 이런 데이터라고 생각해보겠습니다.
[
[ 0.5, -0.3, 1.2],
[-1.1, 0.8, -0.7]
]
여기서 음수 값만 찾고 싶다면 어떻게 해야 할까요?
13. 조건식을 그대로 사용할 수 있습니다
arr < 0
이라고 하면 배열 안의 각각의 값에 대해
0보다 작은가?
를 검사합니다.
결과는 다음과 같은 Boolean 배열이 됩니다.
[
[False, True, False],
[True, False, True ]
]
이제 이 조건을 다시 배열에 넣을 수 있습니다.
arr[arr < 0]
그러면 조건이 True인 값들만 추출됩니다.
즉,
음수 값만 추출
할 수 있습니다.
14. 조건에 맞는 값을 바로 변경할 수도 있습니다
원본 학습 자료에서는 음수 값을 오류나 노이즈라고 가정했습니다.
예를 들어 센서 데이터라고 생각해보겠습니다.
측정값은 원래 0 이상이어야 하는데 음수가 들어왔다면 잘못된 데이터라고 볼 수도 있습니다.
그렇다면 음수를 모두 0으로 바꾸고 싶을 수 있습니다.
NumPy에서는 다음 한 줄로 가능합니다.
arr[arr < 0] = 0
이 코드를 말로 풀어보면
arr에서
arr < 0 조건을 만족하는 데이터를 찾고
그 값을 모두 0으로 변경
입니다.
처음 보면 코드가 조금 복잡해 보이지만 구조를 나눠보면 생각보다 단순합니다.
arr < 0
먼저 조건을 만들고,
arr[arr < 0]
조건에 해당하는 데이터를 선택한 다음,
arr[arr < 0] = 0
값을 변경하는 것입니다.
데이터 전처리와 바로 연결되는 부분인 것 같습니다
Boolean Indexing을 공부하면서 가장 먼저 떠오른 것이 데이터 전처리였습니다.
실제 데이터에는 이상한 값이 들어올 수 있습니다.
예를 들어,
나이 = -10
온도 = 비정상 범위
주가 = 0 이하
거래량 = 음수
같은 데이터가 있을 수 있습니다.
이럴 때 조건을 이용해서
잘못된 데이터를 찾고
↓
삭제하거나
↓
보정하거나
↓
다른 값으로 변경
하는 작업을 할 수 있습니다.
그래서 Boolean Indexing은 단순한 배열 문법이라기보다 필터링과 데이터 정제의 기본 개념이라고 이해하면 좋을 것 같습니다.
15. Fancy Indexing은 무엇일까요?
다음은 Fancy Indexing입니다.
이름부터 조금 특별해 보입니다.
일반적인 인덱싱은
arr[0]
처럼 위치 하나를 지정합니다.
Fancy Indexing에서는 여러 인덱스를 한꺼번에 지정할 수 있습니다.
먼저 배열을 하나 만들어보겠습니다.
arr = np.arange(32).reshape(-1, 4)
숫자가 총 32개이고 열이 4개이므로 NumPy가 자동으로 계산해서
(8, 4)
형태가 됩니다.
즉,
[
[ 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]
]
입니다.
원하는 행을 원하는 순서대로 가져올 수 있습니다
예를 들어
arr[[3, 0, 4, 5]]
라고 해보겠습니다.
의미는
3번 행
0번 행
4번 행
5번 행
을 순서대로 가져오라는 것입니다.
즉 반드시 연속된 데이터일 필요가 없습니다.
슬라이싱은 보통
0번부터 4번까지
처럼 연속된 범위를 선택하는 데 강점이 있다면,
Fancy Indexing은
3번
0번
4번
5번
처럼 원하는 위치를 직접 지정할 수 있습니다.
16. 행과 열의 좌표를 직접 지정할 수도 있습니다
조금 더 복잡한 형태도 가능합니다.
arr[
[3, 0, 4, 5],
[2, 1, 0, 3]
]
이 코드는 각각의 행과 열 좌표를 짝지어 선택합니다.
즉,
(3, 2)
(0, 1)
(4, 0)
(5, 3)
위치의 데이터를 가져오는 것입니다.
처음 보면 상당히 복잡해 보이지만,
여러 개의 좌표를 한꺼번에 찍어서 데이터를 가져온다
고 생각하면 조금 이해하기 쉽습니다.
슬라이싱과 Fancy Indexing을 구분해보면
저는 이렇게 기억하려고 합니다.
슬라이싱
→ 연속된 범위
→ 방향성이 있음
Fancy Indexing
→ 원하는 위치를 직접 지정
→ 순서를 마음대로 정할 수 있음
→ 비연속적인 데이터도 가능
예를 들어
1번부터 5번까지
라면 슬라이싱이 편하고,
7번 → 2번 → 5번 → 0번
처럼 가져오고 싶다면 Fancy Indexing이 편합니다.
17. Pandas의 iloc과도 연결됩니다
원본 학습 자료에서는 Fancy Indexing이 이후 Pandas의 iloc과 연결된다고 설명하고 있습니다.
Pandas에서는 다음처럼 위치를 기준으로 데이터를 선택할 수 있습니다.
df.iloc[[3, 0, 4, 5]]
NumPy에서 배열의 위치를 선택하는 개념에 익숙해지면 Pandas의 데이터 선택 방식도 조금 더 쉽게 이해할 수 있을 것 같습니다.
NumPy가 데이터 분석의 기반이라고 하는 이유가 이런 부분에서도 조금씩 보이는 것 같습니다.
18. 이번에는 배열의 축을 바꿔보겠습니다
데이터를 선택하는 것과 조금 다른 기능도 있습니다.
바로 배열의 축을 바꾸는 것입니다.
먼저 shape을 확인해보겠습니다.
arr.shape
그리고
arr.T.shape
을 확인해보겠습니다.
T는 Transpose, 즉 전치라는 의미입니다.
예를 들어 원래 shape이
(8, 4)
였다면,
arr.T
의 shape은
(4, 8)
이 됩니다.
행과 열이 서로 바뀐 것입니다.
19. 전치 행렬을 쉽게 생각해보겠습니다
다음 배열이 있다고 해보겠습니다.
[
[1, 2, 3],
[4, 5, 6]
]
shape은
(2, 3)
입니다.
여기에
arr.T
를 적용하면
[
[1, 4],
[2, 5],
[3, 6]
]
이 됩니다.
shape은
(3, 2)
로 바뀝니다.
즉,
행 ↔ 열
이 서로 뒤바뀐 것입니다.
20. transpose()도 사용할 수 있습니다
T뿐만 아니라
arr.transpose()
도 사용할 수 있습니다.
2차원 배열에서는 기본적으로
arr.T
와 비슷하게 사용할 수 있습니다.
또한
arr.transpose((1, 0))
처럼 어떤 축을 어떤 순서로 배치할지도 지정할 수 있습니다.
2차원에서는
축 0 → 행
축 1 → 열
이라고 생각할 수 있습니다.
따라서
arr.transpose((1, 0))
은
열 → 행
행 → 열
순서로 바꾸는 것입니다.
21. 3차원부터 transpose가 조금 더 재미있어집니다
예를 들어 다음과 같이 배열을 바꿔보겠습니다.
arr = arr.reshape((2, 2, 8))
현재 shape은
(2, 2, 8)
입니다.
이 상태에서
arr.transpose((1, 2, 0))
을 사용할 수 있습니다.
원래 축 순서가
0, 1, 2
였다면,
1, 2, 0
순서로 축을 다시 배치하는 것입니다.
따라서 shape도
(2, 8, 2)
처럼 바뀔 수 있습니다.
처음 보면 꽤 어렵습니다.
현재 단계에서는
transpose는 데이터 자체를 계산하는 것이 아니라 축의 순서를 바꾸는 기능이다.
정도로 이해하면 충분할 것 같습니다.
나중에 이미지 데이터나 딥러닝 데이터를 다룰 때 이런 축 변경을 자주 만나게 된다고 합니다.

22. np.sum(arr)와 arr.sum()은 비슷하게 사용할 수 있습니다
원본 학습 자료 마지막에는 이런 코드도 있습니다.
np.sum(arr)
그리고
arr.sum()
두 방법 모두 배열의 값을 더하는 데 사용할 수 있습니다.
NumPy에는 이런 형태가 꽤 많습니다.
np.xxx(arr)
형태로 사용할 수도 있고,
arr.xxx()
처럼 배열 객체의 메서드로 사용할 수도 있습니다.
예를 들어,
np.sum(arr)
arr.sum()
처럼 사용할 수 있습니다.
처음 배우는 입장에서는
“왜 똑같은 기능이 두 군데에 있지?”
싶을 수 있는데, NumPy에서는 이런 형태를 자주 만나게 되는 것 같습니다.
여기까지 공부해보니 데이터 선택 방식이 꽤 다양했습니다
이번 내용을 정리하면 NumPy에서 데이터를 선택하는 방법은 하나가 아니었습니다.
특정 위치 하나 선택
↓
Indexing
연속된 범위 선택
↓
Slicing
조건으로 선택
↓
Boolean Indexing
원하는 위치를 직접 지정
↓
Fancy Indexing
그리고 데이터의 방향이나 축을 바꾸고 싶다면
arr.T
transpose()
를 사용할 수 있습니다.
개인적으로 Boolean Indexing이 가장 중요하게 느껴졌습니다
이번 글에서 하나만 골라보라고 하면 저는 Boolean Indexing을 기억할 것 같습니다.
예를 들어
arr[arr < 0] = 0
이라는 한 줄이 처음에는 상당히 복잡해 보였습니다.
그런데 나눠보면 단순합니다.
arr < 0
음수인지 검사합니다.
↓
arr[arr < 0]
음수만 선택합니다.
↓
arr[arr < 0] = 0
선택한 값을 0으로 바꿉니다.
즉,
조건 설정
↓
데이터 선택
↓
데이터 수정
이 한 줄에 들어 있습니다.
이 구조는 앞으로 Pandas에서 데이터를 필터링할 때도 계속 만나게 될 것 같습니다.
NumPy 공부를 처음 시작하면서 느낀 점
처음 NumPy를 시작했을 때는
np.array()
만 알면 되는 단순한 라이브러리라고 생각했습니다.
그런데 1부부터 여기까지 공부해보니 꽤 많은 개념이 연결되어 있었습니다.
데이터
↓
ndarray
↓
shape / ndim / dtype
↓
배열 생성
↓
reshape
↓
배열 연산
↓
broadcasting
↓
indexing
↓
filtering
하나씩 따로 공부할 때는 각각 별개의 문법처럼 느껴졌습니다.
그런데 전체 흐름으로 보니 결국 모두
많은 데이터를 원하는 형태로 만들고, 계산하고, 필요한 부분만 꺼내기 위한 기능
이라는 생각이 듭니다.
NumPy가 데이터 분석이나 머신러닝의 기반이라고 하는 이유를 조금씩 이해하게 되는 것 같습니다.
지금까지의 NumPy 시리즈를 정리해보겠습니다
1부
NumPy가 무엇이고 왜 필요한지 알아봤습니다.
NumPy
Pandas
Polars
Spark
ndarray
shape
ndim
dtype
2부
배열을 만드는 방법을 알아봤습니다.
array
asarray
arange
reshape
zeros
ones
empty
eye
identity
random
3부
배열의 계산 방법을 알아봤습니다.
배열 연산
벡터화
브로드캐스팅
dtype
astype
타입 변환
4부
이번에는 데이터를 선택하는 방법을 알아봤습니다.
Indexing
Slicing
Boolean Indexing
Fancy Indexing
T
transpose
처음에는 용어가 굉장히 많아 보였는데 하나씩 연결해서 보니 조금씩 구조가 잡히는 것 같습니다.
NumPy를 처음 공부한다면 모든 함수를 외우려고 하기보다는,
배열을 어떻게 만들까?
↓
shape은 어떻게 바꿀까?
↓
배열끼리 어떻게 계산할까?
↓
원하는 데이터는 어떻게 선택할까?
이 흐름을 먼저 이해하는 것이 더 중요할 것 같습니다.
저도 아직 처음 배우는 단계라 앞으로 실제 데이터를 많이 다뤄보면서 익숙해져야 할 것 같습니다.
'코딩 개발 > Date Engineer' 카테고리의 다른 글
| NumPy 공부 3부 — 배열 연산과 브로드캐스팅, dtype을 이해해보자 (0) | 2026.10.07 |
|---|---|
| NumPy 공부 2부 — ndarray 만드는 방법과 shape, reshape 제대로 이해하기 (0) | 2026.10.06 |
| NumPy 공부 1부 — 데이터 분석을 시작하면 왜 NumPy부터 배우는 걸까? (0) | 2026.10.05 |
| [6편] CloudWatch에서 Kinesis + S3 Data Lake (Bronze Layer) 스트리밍 파이프라인 구축하기 (0) | 2026.10.02 |
| [5편] Docker 컨테이너 빌드부터 AWS ECS 1-Click 대량 실행 파이프라인까지 (0) | 2026.10.01 |