
Boolean Mask란:
Boolean mask는 True 또는 False로 구성(=boolean)된 시퀀스(Series/DataFrame/ndarray/list) 객체를 이용하여 Pandas에서 특정 데이터를 선택하는 등의 마스킹(masking)을 하는 것을 가리킴.
사용방식:
Seriesmask :- column 또는 row 필터링: 특정 condition(
True/Flase로 치환되는 expression)을 통해False가 되는 row 또는 column을 제거. Seriesmask 에서 반환값에는 NA 생성없음 (=제거됨).
- column 또는 row 필터링: 특정 condition(
DataFramemask :- cell 마스킹에 사용됨.
- Boolean mask에서
False에 해당하는 위치의 cell의 값을 NA 로 치환 - NA로 치환되는 cell의 값은 실제로 반환값에서 해당하는 위치의 dtype에 따라
np.nan또는pd.NA임.
where()/mask():- conditional replacement 에 사용됨.
- 해당 메서드에 주어진 condition의 결과
True또는False값에 따라 - 해당 위치의 값이 유지 또는 치환됨.
NA (not available or missing value, 결측치) 종류:
- 다음의 전통 NumPy dtype 은
np.nan사용float64int64object
- 다음의 Pandas 확장 dtype 은
pd.NA사용.Int64Float64stringboolean
1. 예제 코드를 위한 데이터
import pandas as pd
import numpy as np
# 혼합 dtype 예제:
# - name: object(string) 기본 dtype
# - score, speed: int -> pandas가 정수로 유지 (전통 NumPy int64)
# - status: 'string' 확장 dtype(의도적으로 지정) → 결측 시 pd.NA 사용
# - grp: object
df = pd.DataFrame({
"name": ["Alice", "Bob", "Charlie", "David", "Eva"],
"score": [85, 40, 72, 90, 55],
"speed": [33, 27, 31, 36, 29],
"status": pd.Series(["ok", "ng", "ok", "ok", "ng"], dtype="string"),
"grp": ["A", "B", "A", "B", "A"],
})
# 확인: 각 열 dtype
print(df.dtypes)
# name object : 전통 NumPy(object) : 마스킹 시 np.nan
# score int64 : 전통 NumPy(int64) : 마스킹 시 np.nan
# speed int64 : 전통 NumPy(int64) : 마스킹 시 np.nan
# status string : 확장 dtype(string) : 마스킹 시 pd.NA
# grp object : 전통 NumPy(object) : 마스킹 시 np.nan
2. Series mask로 “행(row)” 필터링
- condition을 만족하지 않는 행은 아예 제외 : NA 생성 없음.
- 복수의 condition을 사용하려면 연산자
&(AND),|(OR),~(NOT) 사용하고 각 condition은 parentheses로 감쌈.
2-1. 단일 조건: score >= 70 인 행만 선택
mask_row = (df["score"] >= 70) # Boolean Series (index alignment 보장)
df_row_filtered = df[mask_row] # 행 필터링, 조건 불만족 행은 제거됨
print(df_row_filtered)
2-2. 복합 조건: (grp == 'A') & (speed >= 30)
cond = (df["grp"].eq("A")) & (df["speed"] >= 30)
df_row_filtered2 = df[cond]
print(df_row_filtered2)
2-3. 일부 column 만 보려면: loc로 컬럼 지정
df_row_minimal = df.loc[df["score"] >= 70, ["name", "score", "grp"]]
print(df_row_minimal)
iloc의 사용도 가능한데,["name", "score", "grp"]의 일부 column 지정을 0 이상의 정수 index로 바꿔야 함:[0,1,4]- 행 조건:
df["score"] >= 70은 Boolean Series로iloc에서도 Boolean mask로 동작함. 단iloc은 이 경우Series의 index를 무시하고 위치기반으로만 동작.
3. Series mask로 “열(column)” 필터링
- 다음의 예제는 label이 ‘s’로 시작하는 복수의 column을 필터링:
score,speed,status3개. - column에 대한 boolean mask는 columns size와 동일 길이여야 하며,
- 이 마스크를
Series개체로 쓰는 경우index가df.columns와 일치해야함.
3-1. ndarray[bool] 마스크로 's' 시작 열만 선택 → 여러 열(score, speed, status) 유지
cols_mask = df.columns.str.startswith("s") # 예: [False, True, True, True, False]
df_cols_filtered = df.loc[:, cols_mask] # 열 필터링, NaN 생성 없음(열 제거 방식)
print(df_cols_filtered)
3-2. Boolean Series 마스크로 동일 동작 (index를 columns에 정렬)
cols_mask_series = pd.Series(cols_mask, index=df.columns)
df_cols_filtered2 = df.loc[:, cols_mask_series]
print(df_cols_filtered2)
3-3. 문자열 패턴 활용(참고): 's'로 시작하고 'e' 포함 열만
advanced_cols_mask = df.columns.str.match(r"^s") & df.columns.str.contains("e")
print(df.loc[:, advanced_cols_mask]) # 여기서는 score, speed 중 'e'가 있는 speed만 남음
4. DataFrame mask로 “셀(cell)” 마스킹
- 이 경우
False위치를 결측치로 치환하고 DataFrame mask와 같은 shape의 반환값을 가짐.
4-1. DataFrame 전체 조건 생성: 각 열에 서로 다른 기준
mask_df = pd.DataFrame({
# name: 길이 > 3인 이름만 남기고, 아니면 결측치로
"name": (df["name"].str.len() > 3),
# score: 60 초과만 남기고, 아니면 결측치로
"score": (df["score"] > 60),
# speed: 30 이상만 남기고, 아니면 결측치로
"speed": (df["speed"] >= 30),
# status: 값이 'ok'인 곳만 남기고, 아니면 결측치로
"status": (df["status"].eq("ok")),
# grp: 'B'인 곳만 남기고, 아니면 결측치로
"grp": (df["grp"].eq("B")),
})
4-2. 셀 마스킹: False: 결측치로 치환
masked = df[mask_df] # df.where(mask_df)와 동일 효과
print(masked)
- 반환되는
masked의 전통적인 NumPy 데이터 타입인 column은 다음과 같음.name(NumPy object),score(int64),speed(int64),grp(object)
- NumPy 데이터 타입인 경우, boolean mask에서
False의 위치는np.nan로 표시 - Pandas의 확장 데이터 타입인
status(string 확장 dtype)에서 False 위치는<NA>로 표시:pd.NA
주의: int64 열이 결측을 갖게 되면
내부적으로 float로 upcast되어 보일 수 있음
(이 경우 소수점으로 출력됨).
위의 column filtering을 위한 boolean mask mask_df를 row filtering으로 전환가능:
mask_df.all(axis=1): 모든 열 조건이 True인 행만 유지.mask_df.any(axis=1): 하나라도 True인 행 유지.
4-3. DataFrame mask: 행 필터 조건으로 축약
rows_all_true = df[mask_df.all(axis=1)] # 모든 열 조건 만족 행만
rows_any_true = df[mask_df.any(axis=1)] # 하나라도 만족하는 행
print(rows_all_true)
print(rows_any_true)
5. where()/mask()로 조건부 대치 (False 위치를 NaN 또는 다른 값으로 대치)
where(cond, other=np.nan):cond=True: 유지cond=False:other에 할당된 값으로 대치.
- mask(cond, other=np.nan):
cond=True: other로 대치cond=False: 유지.
other가 미지정시 dtype에 따른 NA로 처리됨.
5-1. Series where - NumPy 타입
- 전통 NumPy dtype(
float64) :False위치는np.nans_float = pd.Series([10.0, 20.0, 30.0], dtype="float64") out1 = s_float.where(s_float > 15) # 15 초과만 유지, 나머지는 np.nan print(out1)
5-2. Series where - 확장 타입
- 확장 dtype(
Int64) :False위치는pd.NAs_int_ext = pd.Series([10, 20, 30], dtype="Int64") out2 = s_int_ext.where(s_int_ext > 15) # 15 초과만 유지, 나머지는 <NA>(pd.NA) print(out2)
5-3. DataFrame where - Broad Casting
- 단일 조건의 결과 값이 브로드캐스팅
# score >= 70인 행은 유지, 그 외 행의 모든 셀은 결측치로 대치 out3 = df.where(df["score"] >= 70) print(out3) # 해석: # - name/score/speed/grp(object,int 등 전통 dtype): np.nan # - status(string 확장 dtype): pd.NA
5-4. False 위치를 NaN이 아닌 다른 값으로 대치 - 권장
- 다음의 예는
score<70인 행의'score'만-1로 바꾸는 식으로 열 단위 치환을 수행.
df_score_replaced = df.copy()
df_score_replaced["score"] = df["score"].where(df["score"] >= 70, other=-1) # 미달 점수 -1
print(df_score_replaced)
5-5. where()의 반대 동작: mask()
mask(cond, other) = where(~cond, other)
s_masked = s_float.mask(s_float > 15, other=-999) # 15 초과인 곳만 -999로 치환
print(s_masked)
6) 주의할 점
- multiple condition의 경우 bitwise operation 이용:
- boolean op. 인
and/or/not사용 못함. &/|/~사용.
- boolean op. 인
- multiple condition의 경우 각 개별 condition은 괄호(
( ))로 감싸기. - NA (or missing value) 전파:
DataFrame마스킹 및where()에서False에 따른 NA 발생.- 이후
fillna/dropna의 사용을 통한 처리도 많이 이용됨.
- 성능 및 가독성을 위해 복잡한 condition은 변수로 보관하여 재사용할 것.
7. 요약
Seriesmask- 행/열 필터링
False위치의 데이터는 제거, NA 생성 없음.
DataFramemask- 셀 마스킹
- False 위치를 결측치로 치환.
where()/mask()- 조건부 대치
False위치를 임의의 값으로 치환 가능- 브로드캐스팅·열별 적용 유연.
같이보면 좋은 자료들
2024.03.18 - [Python] - [DL] Tensor: Indexing <Simple, Slicing, Fancy, Boolean Mask>
[DL] Tensor: Indexing <Simple, Slicing, Fancy, Boolean Mask>
NumPy나 PyTorch, Tensorflow의 텐서들도파이썬의 list 또는 tubple 에서의 indexing과 slicing이 거의 그대로 사용됨.2023.07.12 - [Python] - [Python] list (sequence type) : summary [Python] list (sequence type) : summarylist는 ordered m
ds31x.tistory.com
2024.03.19 - [Python] - [ML] where: numpy 의 idx찾기
[ML] where: numpy 의 idx찾기
np.where 함수numpy에서 ndarray 인스턴스에서 특정 조건을 만족하는 elements의 위치(index, idx)를 찾는 기능을numpy 모듈의 where 함수가 제공해줌.사실 where 함수는 특정 조건에 따라 값을 바꾸어주는 기능
ds31x.tistory.com
2025.05.16 - [Python/pandas] - [ML] pandas.DataFrame 에서 EDA에 적합한 메서드 요약
[ML] pandas.DataFrame 에서 EDA에 적합한 메서드 요약
Pandas DataFrame에서 탐색적 데이터 분석(EDA)에 사용할 수 있는 주요 메서드들은 다음과 같음:2024.05.18 - [분류 전체보기] - [ML] Exploratory Data Analysis (EDA) [ML] Exploratory Data Analysis (EDA)Exploratory Data Analysis (
ds31x.tistory.com
'Python > pandas' 카테고리의 다른 글
| [Pandas] 차트 그리기-plot (0) | 2025.09.05 |
|---|---|
| [Pandas] isin() 메서드: 가독성 높은 boolean mask 만들기. (2) | 2025.08.28 |
| [Pandas] index 와 columns- 관련 메서드: rename(), set_index(), reset_index() (0) | 2025.08.24 |
| [Pandas] melt() 메서드 (2) | 2025.08.24 |
| [Pandas] missing value 확인: 결측치 확인 (0) | 2025.08.24 |