[초급] Pandas ValueError, 이 코드 한 줄 모르면 당신의 데이터는 쓰레기통으로 직행함

[초급] Pandas ValueError, 이 코드 한 줄 모르면 당신의 데이터는 쓰레기통으로 직행함

결론부터 말한다. 99%의 원인은 이거다.

데이터 전처리 과정에서 마주치는 ValueError. 이 골치 아픈 에러는 대부분 결측치(NaN) 즉 빠진 데이터 때문이다. 시스템 입장에선 당연한 반응이다. 숫자로 계산해야 할 칸에 정체불명의 빈칸(NaN)이 들어 있으니, ‘이걸로 뭘 어쩌라는 거냐’며 작업을 거부하는 것이다. 이걸 능숙하게 다루지 못하면, 당신이 쌓은 데이터는 그냥 분석 불가능한 디지털 폐기물일 뿐이다.

보통 직장인 열에 아홉은 여기서 막힌다. 그리고 엉뚱한 곳에서 원인을 찾느라 시간을 허비한다. 나도 그랬다. 핵심은 간단하다. 빈칸을 어떻게 ‘처리’할 것인가. 이 관점만 있으면 된다.


흔히 저지르는 치명적인 실수 3가지 (그리고 해결책)

코드를 보여주기 전에, 당신이 삽질할 경로를 미리 알려주겠다. 아마 이 순서대로 실수를 저지를 확률이 높다.

❌ 실수 1: 상황 파악 없이 `dropna()`부터 쓰고 본다.

가장 흔하고, 가장 위험한 접근법이다. 일단 에러가 보기 싫으니 결측치가 포함된 행이나 열을 통째로 날려버리는 것. 이건 데이터를 정제하는 게 아니라, 그냥 내다 버리는 행위다.

상황: 1000개의 고객 데이터 중 단 10개의 행에만 주소 정보가 비어있다. 그런데 `df.dropna()`를 실행. 결과는? 주소 외에 이름, 나이, 구매 기록 등 멀쩡한 데이터가 있던 10명의 고객 정보가 통째로 증발한다. 1000개 데이터가 990개가 되는 마법. 이게 작은 규모니 이 정도지, 데이터가 복잡해지면 절반 이상이 날아가는 것도 순식간이다.

💡 해결책: 삭제의 기준을 명확히 제시해야 한다. 시스템은 당신의 의도를 읽지 못한다.

  • 특정 열의 결측치만 제거: `df.dropna(subset=[‘address’])` → 주소 열이 비어있는 행만 정확히 타격한다.
  • 데이터가 일정 수준 이상 없는 행만 제거: `df.dropna(thresh=5)` → 최소 5개 이상의 유효한 데이터가 없는 행만 제거한다.

❌ 실수 2: 모든 빈칸을 `fillna(0)`으로 통일한다.

‘삭제는 위험하다’는 걸 깨달은 다음 단계의 실수다. 일단 빈칸을 채우긴 채워야겠는데, 마땅한 값이 생각나지 않으니 만만한 숫자 ‘0’으로 다 채워버린다.

상황: 직원들의 월 소득 데이터를 분석하는데, 일부 신입사원의 데이터가 아직 입력되지 않아 비어있다. 여기에 `df[‘income’].fillna(0)`을 적용. 결과는? 평균 소득을 계산하니, 소득 0원짜리 직원이 대거 포함되어 전체 평균값이 터무니없이 낮아진다. 월 소득 0원과 ‘아직 모름’은 완전히 다른 정보다.

💡 해결책: 데이터의 맥락에 맞는 값으로 채워야 한다. 이건 자동화가 아니라, 논리적 판단의 영역이다.

  • 평균값/중앙값으로 채우기: `mean_income = df[‘income’].mean()` → `df[‘income’].fillna(mean_income)` → 가장 보편적이고 합리적인 방법.
  • 앞/뒤 데이터로 채우기: `df[‘stock_price’].fillna(method=’ffill’)` → 시계열 데이터처럼 순서가 중요할 때, 바로 앞 데이터로 채운다. (ffill: forward fill)

❌ 실수 3: 값만 보고 데이터 타입(dtype)을 무시한다.

눈에는 분명히 숫자로 보이는데, 시스템은 문자로 인식하는 경우가 허다하다. ‘123’과 123은 완전히 다른 존재다. 전자는 글자, 후자는 숫자다. 글자에다 사칙연산을 시키니 `ValueError`를 뱉는 건 당연하다.

상황: 웹에서 긁어온 데이터에 ‘3,000원’ 같은 형식의 가격 정보가 있다. 여기서 ‘원’과 쉼표(,)를 제거하고 ‘3000’으로 만들었지만, 여전히 데이터 타입은 ‘object'(문자열)다. 이걸 모르고 평균 가격을 계산하려고 하니 계속 에러가 발생한다.

💡 해결책: 결측치 처리 후, 혹은 처리 전에 반드시 데이터 타입을 확인하고 변환하는 습관을 들여야 한다.

  • 숫자로 강제 변환: `pd.to_numeric(df[‘price’], errors=’coerce’)` → 이 코드가 핵심이다. `errors=’coerce’` 옵션은 숫자로 바꿀 수 없는 값을 만나면, 에러를 뱉는 대신 알아서 NaN으로 바꿔준다. 이렇게 변환된 NaN을 위에서 배운 `fillna`나 `dropna`로 처리하면 완벽하다.

결론: 이 3가지만 기억하면 된다.

Pandas 결측치 처리는 복잡한 알고리즘이 아니다. 데이터 파이프라인의 가장 기본이 되는 ‘배관 청소’ 작업이다. 이물질(NaN)을 발견했을 때, 이걸 버릴지(dropna), 다른 걸로 대체할지(fillna), 아니면 재질 자체를 바꿀지(astype) 결정하는 과정일 뿐.

1. 무작정 지우지 마라. (삭제 기준 명시)
2. 의미 없이 채우지 마라. (맥락에 맞는 값 선택)
3. 타입을 확인하고 바꿔라. (숫자처럼 보여도 믿지 말 것)

이 세 가지 원칙만 시스템 구축 초기에 잡아두면, `ValueError` 때문에 야근할 일은 없다.


PipeMaster-Lab 운영정책 및 제보 안내

① 공개된 모든 기록은 특정 기업이나 개인의 청탁 또는 금전적 지원 없이, 시스템 아키텍트의 독립적인 연구 및 실험 결과를 바탕으로 작성됩니다.
② 인용된 외부 콘텐츠 해석에 이의가 있는 경우,
연구실 직통 메일 pipemaster.lab@gmail.com
으로 연락 주시면 24시간 내 회신 및 즉각 조치합니다.
③ 게시된 내용 중 버전 변경으로 인한 정보 불일치나 치명적인 로직 오류를 제보해 주시는 분께는 내부 검토 후 소정의 기프티콘 등 바운티를 지급합니다.
④ 기업 단위의 시스템 아키텍처 컨설팅, 비즈니스 제휴 및 고도화 제안 역시 해당 공식 메일로만 수신 및 회신합니다.
verified

PIPEMASTER RESEARCH LAB

20년 IT 내공과 AI가 결합된 실전 무인 수익 자동화 시스템 연구소
본 콘텐츠는 PipeMaster-Lab 내부 Certified 규격을 엄격히 통과하였음을 증명합니다.

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다