라떼군 이야기
Pandas fillna 사용 시 발생하는 Downcasting FutureWarning 해결 방법
Problem
Pandas DataFrame이나 Series에서 fillna, ffill, bfill 메서드를 사용할 때 다음과 같은 경고 메시지가 발생하는 경우가 있습니다.
FutureWarning: Downcasting object dtype arrays on .fillna, .ffill, .bfill is deprecated and will change in a future version. Call result.infer_objects(copy=False) instead.
이 문제는 주로 데이터 타입을 object로 변환한 후 결측치(NaN)를 빈 문자열("")이나 0과 같은 특정 값으로 채우려 할 때, 혹은 tabulate와 같은 라이브러리로 출력을 예쁘게 다듬으려 할 때 자주 발생합니다.
Background
이 경고는 Pandas의 향후 버전(3.0 이상)에서 ‘조용한 다운캐스팅(Silent Downcasting)’ 기능이 제거될 예정이기 때문에 발생합니다. 기존 Pandas는 object 타입의 배열에 fillna를 수행할 때, 결과 데이터에 맞춰 자동으로 더 효율적인 데이터 타입(예: float, bool)으로 변환(다운캐스팅)을 시도했습니다.
하지만 이러한 암시적 형변환은 데이터 처리 파이프라인에서 예측하지 못한 결과를 초래할 수 있어, Pandas 개발팀은 이를 deprecated(사용 중단 예정) 처리했습니다. 이제 개발자는 데이터 타입 변환이 필요하다면 이를 명시적으로 수행해야 합니다.
Solution
이 경고를 해결하고 코드를 미래의 변경 사항에 대비하게 만드는 방법은 크게 두 가지가 있습니다.
1. 명시적 형변환 사용 (권장)
가장 좋은 방법은 Pandas가 타입을 추론하게 두지 않고, 개발자가 의도한 타입을 명시적으로 지정하는 것입니다. fillna 전후에 .astype()을 사용합니다.
import pandas as pd
import numpy as np
# 예시 데이터 생성
df = pd.DataFrame({'A': [1, np.nan, 3]})
# 기존 방식 (경고 발생 가능성 있음)
# filled = df.fillna(0)
# 해결책: 타입을 명확히 지정
# 결측치를 채운 후 명시적으로 float이나 int로 변환
filled_safe = df.fillna(0).astype(int)
print(filled_safe)
2. future.no_silent_downcasting 옵션과 infer_objects 사용 (범용적 해결)
데이터 타입을 미리 특정하기 어렵거나, 기존 동작을 유지하면서 경고만 해결하고 싶다면 pd.option_context를 사용하여 새로운 동작 방식을 명시적으로 채택(opt-in)하고, 필요한 경우 infer_objects를 호출합니다.
import pandas as pd
import numpy as np
ser = pd.Series([False, True, np.nan])
# 'future.no_silent_downcasting' 옵션을 True로 설정하여
# "나는 다운캐스팅이 없다는 것을 인지하고 있다"고 Pandas에 알림
with pd.option_context("future.no_silent_downcasting", True):
# fillna 수행 후 infer_objects를 호출하여 적절한 타입으로 추론 유도
result = ser.fillna(False).infer_objects(copy=False)
print(result)
3. Tabulate 출력을 위한 문자열 변환
질문자와 같이 단순히 출력을 위해 NaN을 빈 문자열로 바꾸려는 경우, 모든 데이터를 먼저 문자열로 변환하는 것이 안전할 수 있습니다.
# 단순히 출력을 위한 목적이라면 전체를 문자열로 취급
print_df = df.astype(str).replace('nan', '')
# 이후 tabulate 사용
Deep Dive
infer_objects(copy=False)의 역할
infer_objects 메서드는 object 타입의 DataFrame이나 Series를 더 구체적인 타입(soft type)으로 변환을 시도합니다. fillna가 더 이상 자동으로 타입을 변경해주지 않으므로, fillna 실행 후 infer_objects를 호출하면 기존의 ‘자동 형변환’과 유사한 결과를 명시적으로 얻을 수 있습니다.
전역 설정 주의
pd.set_option("future.no_silent_downcasting", True)를 사용하여 전역적으로 설정을 변경할 수도 있지만, 이는 코드의 다른 부분에 의도치 않은 영향을 줄 수 있으므로 with pd.option_context(...)를 사용하여 필요한 부분에만 적용하는 것이 안전합니다.
Conclusion
Pandas는 데이터 타입 처리를 더 엄격하고 예측 가능하게 만들기 위해 암시적 다운캐스팅을 제거하고 있습니다. FutureWarning을 무시하지 말고, 가능하면 .astype()을 통해 명시적으로 타입을 지정하거나, infer_objects()와 옵션 컨텍스트를 활용하여 코드를 최신 표준에 맞게 수정하는 것이 좋습니다.