[Pandas] clip / where / mask
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]| original | clipped (0, 100) |
|---|---|
| -5 | 0 |
| 0 | 0 |
| 50 | 50 |
| 150 | 100 |
| 200 | 100 |
컬럼별 다른 경계
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 로 강등
💬 댓글