본문으로 건너뛰기
김신건의 로그

[Pandas] clip / where / mask

· 수정 · 📖 약 1분 · 265자/단어 #python #pandas #conditional #clip
Pandas clip, Pandas where, Pandas mask, 조건부 갱신 pandas

정의

  • clip(lower, upper) : 범위 밖 값을 경계로 자르기 (outlier 처리)
  • where(cond, other) : cond 가 True 면 유지, False 면 other 로 치환
  • mask(cond, other) : where 의 반대 (cond True 가 치환)

clip

s.clip(lower=0)               # 0 미만 → 0
s.clip(upper=100)              # 100 초과 → 100
s.clip(lower=0, upper=100)     # [0, 100] 범위로
python
import pandas as pd
s = pd.Series([-5, 0, 50, 150, 200])
print(s.clip(0, 100).tolist())
결과
[0, 0, 50, 100, 100]
originalclipped (0, 100)
-50
00
5050
150100
200100

컬럼별 다른 경계

df.clip(lower={'a': 0, 'b': -10}, upper={'a': 100, 'b': 10})

where

s.where(cond, other)        # cond True 면 그대로, False 면 other

IMPORTANT

s.where(cond, other)cond 가 True 일 때 그대로 유지. numpy 의 np.where(cond, a, b) 와 의미가 정반대다.

python
import pandas as pd
s = pd.Series([10, 20, 30, 40])
print(s.where(s > 20, 0).tolist())
결과
[0, 0, 30, 40]

s > 20 이 False 인 위치 (10, 20) 가 0 으로 치환됨.

where 의 함수 형태

s.where(lambda x: x > 0, 0)              # cond 도 callable
s.where(s > 0, lambda x: -x)             # other 도 callable

mask

s.mask(cond, other)         # where 의 반대

cond True 인 곳을 치환. 의미가 더 직관적인 경우가 많다.

# salary 가 100k 이상이면 'high', 아니면 NaN
df['tier'] = df['salary'].mask(df['salary'] < 100000, 'low')
df['tier'] = df['salary'].mask(df['salary'] >= 100000, 'high')

np.where 와의 비교

import numpy as np
np.where(s > 20, s, 0)        # cond True → s, False → 0
s.where(s > 20, 0)             # cond True → s, False → 0 (같음)

같은 결과지만 pandas API 는 other 가 cond False 일 때, numpy 는 x 가 True 일 때.

np.select (다중 분기)

import numpy as np
conditions = [df['age'] < 13, df['age'] < 20, df['age'] < 65]
choices = ['child', 'teen', 'adult']
df['stage'] = np.select(conditions, choices, default='senior')

여러 if-elif-else 를 벡터화.

자주 쓰는 패턴

outlier 처리

# 1, 99 percentile 로 clip
lower = df['amount'].quantile(0.01)
upper = df['amount'].quantile(0.99)
df['amount_clipped'] = df['amount'].clip(lower, upper)

NaN 으로 outlier 마킹

df['amount'] = df['amount'].mask(
    (df['amount'] < 0) | (df['amount'] > 10000),
    other=pd.NA,
)

조건부 컬럼 생성

df['discount'] = df['price'].where(df['vip'], df['price'] * 0.9)
# vip 이면 그대로, 아니면 10% 할인

함정

1. where / mask 의 의미 헷갈림

기억법: where 는 when True 유지. mask 는 masks True (가린다).

2. cond 의 shape 일치

df.where(some_bool_df)        # 같은 shape DataFrame
df.where(df['x'] > 0)         # broadcast (행 단위)

3. other 의 dtype

s = pd.Series([1, 2, 3], dtype='int64')
s.where(s > 1, 'small')       # dtype 이 object 로 강등

참고

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기