P2-11.4 보충학습: NumPy에서 모양(shape)과 원본 공유를 함께 읽는 법¶
Section ID:
P2-11.4Version:v2026.07.20
P2-11.2에서는 인덱싱(indexing), 슬라이싱(slicing), 축(axis)을 봤고, P2-11.3에서는 브로드캐스팅(broadcasting)과 벡터화(vectorization)를 봤습니다. 그런데 실제 NumPy 코드를 읽다 보면 그 다음에 자주 막히는 질문이 남습니다.
이 선택은 원본 배열을 그대로 보고 있는가? 아니면 새 배열을 하나 만든 것인가? shape를 왜 갑자기 (3,)에서 (3, 1)로 바꾸는가?
이 보충학습은 그 질문을 묶어서 다룹니다.
여기서는 불리언 마스크(boolean mask), 팬시 인덱싱(fancy indexing), np.newaxis, 원본 공유(shared view)를 묶어 보는 기본 설명을 제공합니다. 앞 절들의 인덱싱, 슬라이싱, 브로드캐스팅이 읽히더라도, 선택 방식과 shape 변화가 원본 공유와 어떻게 연결되는지는 여기 기준으로 다시 연결합니다.
처음 읽는 기준: NumPy에서 모양(shape)과 원본 공유를 함께 읽는 법¶
- 기본 슬라이싱은 원본 배열의 일부를 보는 방식으로 자주 읽힌다고 설명할 수 있습니다.
- 팬시 인덱싱과 불리언 마스크는 새 배열을 만드는 방식으로 자주 읽힌다고 설명할 수 있습니다.
shape가 같아 보여도 원본 공유 여부는 다를 수 있음을 설명할 수 있습니다.np.newaxis를 길이 1인 축을 추가하는 표기로 설명할 수 있습니다.- broadcasting 코드를 읽을 때
값,shape,원본 공유를 함께 점검해야 함을 설명할 수 있습니다.
먼저 붙잡을 한 장면¶
이 보충학습에서 가장 먼저 붙잡아야 할 장면은 어떻게 골랐는가와 shape를 어떻게 바꿨는가가 원본 공유와 계산 방향을 함께 바꾼다는 점입니다.
| 코드 장면 | 먼저 읽는 질문 | 지금 붙잡을 핵심 |
|---|---|---|
x[1:4] | 구간을 그대로 보고 있는가 | 원본 공유 가능성이 크다 |
x[[1, 3, 4]] | 위치를 따로 모으는가 | 새 배열처럼 읽는 편이 안전하다 |
x[x >= 80] | 조건에 맞는 값만 걸러내는가 | 새 배열처럼 읽는 편이 안전하다 |
x[:, np.newaxis] | 축을 하나 더 추가하는가 | shape가 바뀌고 broadcasting 읽기가 달라진다 |
즉 NumPy에서는 일부를 골랐다는 말만으로는 부족합니다. 구간 보기, 위치 모으기, 조건 걸러내기, 축 추가하기를 먼저 나눠 읽어야 view/copy, shape, broadcasting을 함께 이해할 수 있습니다.
배경¶
P2-8.7 보충학습에서는 Python 리스트와 복사에서 원본이 같이 바뀌는가를 먼저 봤습니다. NumPy에서도 같은 질문이 다시 나옵니다. 다만 NumPy에서는 복사했는가만 보는 것으로 부족하고, shape가 어떻게 바뀌었는가도 함께 봐야 합니다.
예를 들어 같은 x[1:4]와 x[[1, 3, 4]]도 둘 다 일부 값만 고른 것처럼 보이지만, 하나는 원본을 함께 볼 수 있고 다른 하나는 새 배열을 만들 수 있습니다. 또 x[:, np.newaxis]는 값을 바꾸지 않아도 shape를 바꿔 broadcasting 방식 전체를 바꿉니다.
이 절은 P2-11.2에서 슬라이싱과 축은 읽히지만 이 선택이 원본을 같이 바꾸는가가 헷갈릴 때, 또는 P2-11.3에서 broadcasting은 읽히는데 왜 갑자기 (3, 1)과 (1, 3)이 나오는지 멈출 때 함께 봅니다. 이 기준을 붙잡고 나면 슬라이싱, 축, broadcasting을 shape와 원본 공유까지 함께 읽을 수 있습니다.
세 가지 기준¶
| 기준 | 왜 중요한가 | 이 절에서 필요한 이해 수준 |
|---|---|---|
| 무엇을 골랐는가 | 슬라이싱, 팬시 인덱싱, 마스크를 같은 선택으로 오해하지 않게 해 줍니다. | 위치 범위를 자른 것인지, 특정 위치만 따로 모은 것인지 먼저 구분합니다. |
shape가 어떻게 바뀌는가 | 같은 값이어도 계산 방식이 달라지는 이유를 드러냅니다. | (3,), (3, 1), (1, 3) 차이가 계산 방향을 바꾼다는 점을 이해합니다. |
| 원본을 함께 보는가 | 뒤에서 값 수정이 실험 결과를 바꾸는 상황을 막아 줍니다. | 값을 바꿀 가능성이 있으면 복사 여부를 먼저 점검합니다. |
| 용어 | 이 절에서 먼저 잡을 뜻 |
|---|---|
| 불리언 마스크(boolean mask) | 조건이 참인 값만 골라 남기는 선택 방식입니다. |
| 팬시 인덱싱(fancy indexing) | 여러 위치를 목록처럼 지정해 값을 따로 모으는 선택 방식입니다. |
np.newaxis | 길이 1인 축을 추가해 배열 shape를 바꾸는 표기입니다. |
| 원본 공유(shared view) | 선택 결과가 원본 배열과 연결되어 함께 바뀔 수 있는 상태입니다. |
| 복사(copy) | 원본과 분리된 새 배열을 만드는 방식입니다. |
기본 슬라이싱은 원본의 일부를 보는 방식으로 자주 읽힌다¶
P2-11.2에서 본 슬라이싱은 구간을 남기는 표기였습니다. NumPy에서는 이 기본 슬라이싱이 원본 배열의 일부를 함께 보는 방식으로 자주 동작합니다.
문제 상황: 슬라이싱으로 고른 배열 일부를 바꿨을 때 원본도 같이 바뀌는지 확인합니다. 입력(input): 1차원 배열 scores와 슬라이스 scores[1:4]입니다. 기대 출력(output): 슬라이스에서 바꾼 값이 원본 배열에도 반영됩니다. 확인할 개념: 기본 슬라이싱은 새 배열처럼 보여도 원본과 연결되어 읽힐 수 있다는 점을 봅니다.
출력은 다음과 같습니다.
여기서는 이렇게 읽습니다.
scores[1:4]는 값 세 개를 복사해 따로 모은 것처럼만 보면 위험합니다.- 기본 슬라이싱은 원본 배열의 일부를 보는 방식으로 자주 읽힙니다.
- 그래서 뒤에서 값을 바꾸면 원본도 함께 바뀔 수 있습니다.
이 감각은 P2-8.7에서 본 원본과 복사본이 언제 함께 바뀌는가와 직접 연결됩니다.
팬시 인덱싱과 불리언 마스크는 고른 값을 새로 모은다¶
이번에는 같은 “일부 선택”처럼 보여도 방식이 다른 경우를 봅니다.
문제 상황: 특정 위치만 따로 고르는 팬시 인덱싱과 조건으로 고르는 불리언 마스크가 원본과 어떻게 다른지 비교합니다. 입력(input): 배열 scores, 위치 목록 [1, 3, 4], 조건 scores >= 80입니다. 기대 출력(output): 팬시 인덱싱과 불리언 마스크 결과를 바꿔도 원본 scores는 그대로 남습니다. 확인할 개념: 위치를 따로 모으거나 조건으로 걸러 낸 결과는 새 배열처럼 읽는다는 점을 봅니다.
출력은 다음과 같습니다.
여기서 scores[[1, 3, 4]]는 1번, 3번, 4번 위치 값을 따로 모읍니다. 이런 방식을 팬시 인덱싱이라고 부릅니다.
scores[scores >= 80]는 조건이 참인 값만 고릅니다. 이런 방식은 불리언 마스크라고 부릅니다.
둘 다 여기서는 이렇게 이해합니다.
- 기본 슬라이싱은
구간을 그대로 본다에 가깝습니다. - 팬시 인덱싱과 불리언 마스크는
고른 값을 따로 모은다에 가깝습니다.
그래서 값을 바꿨을 때 원본 공유 여부도 달라집니다.
같은 일부 선택이어도 질문이 다르다¶
슬라이싱, 팬시 인덱싱, 불리언 마스크는 모두 일부 값만 고른다는 점에서는 비슷해 보입니다. 하지만 실제로는 서로 다른 질문에 답합니다.
| 표현 | 먼저 읽을 질문 | 입문 단계의 안전한 해석 |
|---|---|---|
x[1:4] | 어느 구간을 남길까? | 구간 보기 |
x[[1, 3, 4]] | 어느 위치를 따로 뽑을까? | 위치 모으기 |
x[x >= 80] | 어느 조건을 만족하는 값만 남길까? | 조건 걸러내기 |
이 차이를 먼저 구분하면 NumPy 코드가 훨씬 덜 헷갈립니다.
np.newaxis는 길이 1인 축을 추가한다¶
이번에는 값을 고르는 것이 아니라 shape를 바꾸는 표기를 봅니다.
문제 상황: 같은 1차원 배열을 행처럼 볼지, 열처럼 볼지 shape만 바꿔 구분합니다. 입력(input): 1차원 배열 scores와 scores[:, np.newaxis], scores[np.newaxis, :]입니다. 기대 출력(output): (3,), (3, 1), (1, 3) 세 가지 shape가 출력됩니다. 확인할 개념: np.newaxis는 값 자체를 바꾸지 않고 길이 1인 축을 추가해 계산 방향을 바꾼다는 점을 봅니다.
출력은 다음과 같습니다.
세 배열은 담고 있는 숫자는 비슷해 보이지만, 읽는 방식은 다릅니다.
| 표현 | shape | 읽는 법 |
|---|---|---|
scores | (3,) | 길이 3인 1차원 배열 |
scores[:, np.newaxis] | (3, 1) | 3행 1열 열 벡터처럼 보기 |
scores[np.newaxis, :] | (1, 3) | 1행 3열 행 벡터처럼 보기 |
즉 np.newaxis는 숫자를 새로 만드는 것이 아니라, 배열을 어느 방향으로 계산에 맞출지 정리하는 표기입니다.
np.newaxis는 broadcasting을 의도적으로 만드는 데 자주 쓰인다¶
P2-11.3에서는 (4, 3)과 (3,)처럼 이미 맞는 shape를 봤습니다. 그런데 어떤 계산은 일부러 축을 하나 더 만들어야 읽기 쉬워집니다.
문제 상황: 열 방향과 행 방향을 분리해 두 집합의 차이를 한 번에 계산합니다. 입력(input): 길이 3 배열 a와 길이 2 배열 b입니다. 기대 출력(output): (3, 1)과 (1, 2)가 만나 (3, 2) 결과가 만들어집니다. 확인할 개념: np.newaxis는 broadcasting을 위한 shape 정렬 도구라는 점을 봅니다.
출력은 다음과 같습니다.
이 예제의 핵심은 값보다 shape입니다.
a[:, np.newaxis]는(3, 1)입니다.b[np.newaxis, :]는(1, 2)입니다.- 두 배열은 broadcasting으로
(3, 2)결과를 만듭니다.
여기서는 np.newaxis를 broadcasting을 위해 행과 열 역할을 더 분명하게 만드는 표기로 이해합니다.
실무형 코드에서는 shape와 원본 공유를 같이 본다¶
NumPy 코드가 헷갈리는 이유는 무엇을 골랐는가와 shape가 어떻게 바뀌는가, 원본이 같이 바뀌는가가 한 줄에서 함께 걸리기 때문입니다.
예를 들어 다음처럼 읽는 습관이 안전합니다.
- 이 코드는 구간을 잘랐는가, 위치를 모았는가, 조건으로 걸렀는가?
- 결과
shape는 무엇인가? - 뒤에서 값을 바꿀 일이 있는가?
- 원본을 보존해야 하면
.copy()가 필요한가?
특히 데이터 전처리에서는 이 판단이 중요합니다. 일부 샘플만 골라 새 데이터셋을 만드는지, 기존 배열 일부를 직접 수정하는지에 따라 실험 결과 해석이 달라질 수 있기 때문입니다.
이 흐름을 한 번에 묶으면 다음과 같습니다.
flowchart TD
select["값 선택 방식<br/>슬라이스 / 팬시 / 마스크"]
share["원본을 함께 보는가<br/>view인지 copy인지"]
reshape["newaxis로 shape 변경<br/>축이 어떻게 바뀌는가"]
broadcast["broadcasting 규칙<br/>어떻게 맞춰 계산되는가"]
result["계산 결과와 부작용<br/>값 변화와 원본 영향"]
select --> share
select --> reshape
reshape --> broadcast
share --> result
broadcast --> result
독자가 여기서 남겨야 할 최소 문장은 다음입니다.
어떻게 골랐는가가 원본 공유를 바꾸고,shape를 어떻게 바꿨는가가 broadcasting 방향을 바꾼다.
어디로 돌아가야 하나¶
이 절을 읽은 뒤에는 다음 본문으로 다시 연결해 읽습니다.
| 지금 다시 읽을 질문 | 먼저 돌아갈 본문 |
|---|---|
| 어느 값이나 구간을 고른 것인가 | P2-11.2 인덱싱, 슬라이싱, 축 |
| 왜 배열 전체 계산이 shape에 따라 달라지는가 | P2-11.3 브로드캐스팅과 벡터화 |
| 원본 공유라는 감각 자체가 아직 낯설다 | P2-8.7 참조, 얕은 복사, 깊은 복사 |
짧은 복귀 표¶
| 막히는 장면 | 먼저 돌아갈 곳 |
|---|---|
| 인덱싱, 슬라이싱, 축 자체가 아직 헷갈린다 | P2-11.2 |
| broadcasting 방향이 왜 바뀌는지 흐릿하다 | P2-11.3 |
| 원본과 복사본이 왜 함께 바뀌는지 낯설다 | P2-8.7 |
체크리스트¶
x[1:4]와x[[1, 3, 4]]의 차이를 설명할 수 있는가?- 불리언 마스크가 무엇을 고르는지 설명할 수 있는가?
(3,),(3, 1),(1, 3)의 차이를 설명할 수 있는가?np.newaxis가 broadcasting과 왜 연결되는지 설명할 수 있는가?- 원본 보존이 중요할 때
.copy()여부를 먼저 점검해야 한다는 점을 기억하는가? - NumPy 코드를 읽을 때 값만이 아니라
shape와 원본 공유 여부를 함께 봐야 한다는 점을 설명할 수 있는가?
출처와 참고 자료¶
- NumPy Developers, Copies and views, NumPy v2.5 Manual, 확인 날짜: 2026-07-20. view와 copy의 차이, 기본 인덱싱 view, advanced indexing copy,
.base확인 설명의 근거로 사용했다. - NumPy Developers, Indexing on ndarrays, NumPy v2.5 Manual, 확인 날짜: 2026-07-20. 선택 방식에 따라 shape와 원본 공유 여부가 달라지는 설명 확인에 사용했다.
- NumPy Developers, Broadcasting, NumPy v2.5 Manual, 확인 날짜: 2026-07-20.
np.newaxis와 shape 조정이 broadcasting 이해와 연결되는 설명의 근거로 사용했다.