factorize() : 고유값을 정수 코드로 변환. ML 전처리의 label encoding.
사용 상황
함수
주요 사용
반환
Series.mode()
최빈값 찾기, 범주형 결측치 채우기
Series (동률 시 여러 값)
DataFrame.mode()
각 컬럼의 최빈값
DataFrame
pd.factorize(s)
문자열 카테고리 정수 인코딩
(codes, uniques) 튜플
카테고리 처리 전략 비교
flowchart LR
A["문자열 카테고리 Series"] --> B["mode()"]
A --> C["factorize()"]
A --> D["astype('category')"]
A --> E["get_dummies()"]
B --> F["최빈값 하나 또는 여러 개"]
C --> G["정수 코드 배열"]
D --> H["Categorical dtype"]
E --> I["원-핫 인코딩 DataFrame"]
mode 기본
python
import pandas as pds = pd.Series(['A', 'B', 'A', 'C', 'B', 'A', 'B'])print('mode():', s.mode().tolist())print('첫 번째 최빈값:', s.mode().iloc[0])
결과
mode(): ['A', 'B']첫 번째 최빈값: A
A, B 둘 다 3 번 등장 → 동률, mode() 가 둘 다 반환. 하나만 필요하면 .iloc[0].
mode 가 여러 값을 반환하는 이유
mode() 는 최빈값이 여러 개면 모두 포함한 Series 를 반환한다. 단 하나인 경우도 Series. 인덱스는 0, 1, 2 … 순서.
s.mode() # Series (0개~여러 개)s.mode().iloc[0] # 첫 번째 최빈값 (가장 자주 쓰임)s.mode().tolist() # 리스트로
DataFrame.mode (컬럼별)
python
import pandas as pdimport numpy as npdf = pd.DataFrame({ 'city': ['Seoul', 'Busan', 'Seoul', 'Daegu'], 'plan': ['pro', 'basic', 'pro', 'pro'],})print(df.mode())
결과
city plan0 Seoul pro
각 컬럼별 최빈값. 동률인 컬럼은 행이 여러 개, 나머지 셀은 NaN.
# 각 컬럼의 최빈값만 (동률 없을 때)modes = df.mode().iloc[0]
groupby + mode (그룹별 최빈값)
# 각 도시에서 가장 흔한 플랜df.groupby('city')['plan'].agg(lambda x: x.mode().iloc[0])
agg 에 lambda 로 mode().iloc[0] 를 넘기면 각 그룹의 최빈값 하나를 얻는다.
# 기본: 등장 순서로 코드 할당pd.factorize(s) # Seoul=0, Busan=1, Daegu=2# sort=True: 정렬 후 코드 할당pd.factorize(s, sort=True) # Busan=0, Daegu=1, Seoul=2
factorize 와 NaN
import numpy as nps_with_nan = pd.Series(['A', None, 'B', None, 'A'])codes, uniques = pd.factorize(s_with_nan)print('codes :', codes) # NaN → -1print('uniques:', uniques.tolist()) # uniques 에 NaN 없음
codes : [ 0 -1 1 -1 0]uniques: ['A', 'B']
use_na_sentinel=True (기본): NaN → -1 코드, uniques 에 미포함.
use_na_sentinel=False: NaN 도 고유값으로 처리.
Categorical 과의 관계
flowchart LR
A["문자열 Series"] --> B["factorize()"]
A --> C["astype('category')"]
B --> D["정수 코드 ndarray + Index"]
C --> E["Categorical dtype"]
E --> F["cat.codes 로 정수 접근"]
E --> G["cat.categories 로 unique 접근"]
cat_cols = ['city', 'category', 'plan']code_dict = {}for col in cat_cols: df[f'{col}_code'], code_dict[col] = pd.factorize(df[col])# 나중에 역변환for col in cat_cols: df[col] = code_dict[col][df[f'{col}_code']]
실전 패턴: mode 로 EDA 요약
# 각 컬럼의 최빈값 + 빈도 요약summary = pd.DataFrame({ 'mode': df.mode().iloc[0], 'mode_count': {col: df[col].value_counts().iloc[0] for col in df.columns}, 'unique': df.nunique(),})print(summary)
함정
1. mode 가 항상 1 개라는 착각
s = pd.Series([1, 2, 1, 2])s.mode() # [1, 2] (두 개)s.mode()[0] # 1 (구식, 정수 인덱스 0)s.mode().iloc[0] # ✓ 위치 기반 (명확)
2. factorize codes 가 numpy ndarray
codes, _ = pd.factorize(s)type(codes) # numpy.ndarray (pandas Series 아님)pd.Series(codes) # Series 로 변환해서 사용
3. factorize NaN 처리 혼동
codes, uniques = pd.factorize(s)# NaN 은 -1 코드, uniques 에는 없음# uniques[-1] 은 마지막 원소 → 의도치 않은 역변환 오류# 사전에 dropna 또는 use_na_sentinel=False 로 처리
4. sort=True 로 인한 코드 변경
codes1, _ = pd.factorize(s) # 등장 순 코드codes2, _ = pd.factorize(s, sort=True) # 알파벳 순 코드# 두 결과가 다름 → 저장 후 복원 시 sort 옵션 일치 필요
5. DataFrame.mode 의 NaN 셀
df.mode()# 동률이 없는 컬럼은 행 0 에만 값, 나머지 행은 NaN# 컬럼마다 행 수가 다를 수 있음
💬 댓글