F1 레이스에서 이런 상황을 상상해보자. 피트 크루가 타이어 교체 데이터를 수집했는데, 파일 형식은 제각각이고 일부 데이터는 누락되어 있다. 어떤 랩에서 교체했는지 숫자로 찾아야 할 때도 있고, 타이어 종류 이름으로 찾아야 할 때도 있다. 분석을 시작하기도 전에 데이터 정리에만 시간을 다 쓰게 된다.
pandas 전처리는 바로 이 문제를 해결하는 단계다. 요즘은 AI에게 코드를 짜달라고 요청하는 방식으로 pandas를 활용하는 경우가 많다. 그런데 개념을 모르면 AI에게 정확하게 요청할 수 없다. “결측값 처리해줘”와 “데이터 수가 적으니까 평균값으로 결측값을 채워줘”는 완전히 다른 결과를 낳는다. 이 글에서는 pandas 전처리의 핵심 5단계를 개념 중심으로 정리하고, 각 단계를 AI에게 어떻게 요청하면 되는지까지 함께 다룬다.
pandas 전처리, 왜 먼저 잡아야 하는가
데이터 분석에서 전처리가 차지하는 비중은 생각보다 훨씬 크다. 실무에서는 분석 시간의 절반 이상이 데이터를 다듬는 데 쓰인다고 해도 과언이 아니다.
pandas 전처리를 건너뛰고 분석을 시작하면 두 가지 문제가 생긴다. 첫째, 결측값이 섞인 채로 계산하면 결과 자체가 틀린다. 둘째, 데이터를 잘못 선택하면 분석 대상이 달라진다. 결국 pandas 전처리는 분석의 정확성을 보장하는 첫 번째 관문이다.
AI에게 코드를 받아서 쓰더라도, 어떤 처리가 필요한지 판단하는 건 사람의 몫이다. 그 판단을 위해 개념을 알아야 한다.
CSV·엑셀 파일 입출력 — pandas로 데이터를 불러오는 3가지 방법
파일을 불러오는 함수는 파일 형식마다 다르다. CSV는 read_csv(), 엑셀은 read_excel()을 쓴다. 저장은 각각 to_csv(), to_excel()이다.
형식보다 중요한 건 옵션의 의미를 아는 것이다. 같은 CSV 파일이라도 구분자가 쉼표인지 탭인지에 따라 불러오는 방식이 달라진다. 엑셀은 시트가 여러 개일 수 있기 때문에 어떤 시트를 불러올지 지정해야 한다.
한 가지 자주 생기는 문제가 있다. 장비에서 내보낸 엑셀 파일에는 결측값이 "NAN" 같은 문자열로 저장되어 있는 경우가 있다. 이걸 그냥 불러오면 pandas가 숫자가 아닌 문자열로 인식해서 나중에 수치 연산에서 오류가 난다. 이때는 어떤 문자열을 결측값으로 인식할지 미리 지정해줘야 한다.
저장할 때는 인덱스 포함 여부를 반드시 결정해야 한다. 인덱스를 포함해서 저장하면 파일을 다시 불러올 때 불필요한 열이 생긴다. 대부분의 경우 인덱스는 저장하지 않는 게 낫다.
기타 파일 형식도 알아두면 좋다.
| 형식 | 특징 | 언제 쓰나 |
|---|---|---|
| Parquet | 행 수 제한 없음, 압축 효율 높음 | 수백만 행 이상 대용량 데이터 |
| JSON | 중첩 구조 표현 가능 | DB 연동, API 응답 데이터 |
| Pickle | 파이썬 전용, 빠른 읽기/쓰기 | 중간 결과 임시 저장 |
실무에서는 CSV와 엑셀이 대부분이다. 데이터가 수백만 행을 넘어가면 Parquet를 고려한다.
# 개념 확인용 예시
df = pd.read_csv('data.csv') # CSV 기본 로드
df = pd.read_excel('data.xlsx', sheet_name='Sheet1') # 엑셀 특정 시트 로드
AI 프롬프트 예시
“data.xlsx 파일을 pandas로 불러오는 코드 짜줘. Sheet2 시트를 불러오고, ‘NAN’과 ‘-‘ 문자열은 결측값으로 처리해줘. 저장할 때는 인덱스 없이 output.xlsx로 저장해줘.”
결측값(NaN) 처리 — dropna vs fillna 언제 쓰는가
결측값은 데이터에 값이 없는 상태다. pandas는 이를 NaN으로 표시한다. 결측값을 그대로 두면 연산 결과가 NaN으로 전파되기 때문에 반드시 처리해야 한다.
처리 전에 먼저 현황을 파악해야 한다. 컬럼별로 결측값이 몇 개인지 확인하는 게 출발점이다. 결측값이 전체 데이터의 몇 퍼센트인지, 어느 컬럼에 집중되어 있는지에 따라 처리 방식이 달라진다.
처리 방법은 크게 두 가지다.
제거(dropna) — 결측값이 있는 행 또는 열을 삭제한다. 데이터 수가 충분하고, 결측값이 소수일 때 쓴다. 결측 행을 날려도 분석에 영향이 없다고 판단될 때만 사용한다.
대체(fillna) — 결측값을 다른 값으로 채운다. 데이터 수가 적어서 한 행도 버리기 아까울 때, 또는 시계열 데이터처럼 앞 값으로 채워도 의미가 있을 때 쓴다. 대체값으로는 컬럼의 평균값, 중앙값, 또는 앞/뒤 값을 주로 사용한다.
| 상황 | 권장 방법 |
|---|---|
| 데이터 수가 충분하고 결측이 소수 | dropna() — 해당 행 삭제 |
| 데이터 수가 적고 모든 행이 중요 | fillna(평균 또는 중앙값) |
| 시계열 데이터, 앞 값이 유효 | fillna(method='ffill') — 앞 값으로 채우기 |
판단 기준은 하나다. “이 결측 행을 날렸을 때 분석 결과가 달라지는가?” 달라진다면 대체, 달라지지 않는다면 제거다.
AI 프롬프트 예시
“df라는 DataFrame에서 결측값 현황을 컬럼별로 확인하는 코드 짜줘. 그리고 ‘temperature’ 컬럼은 평균값으로 결측값을 채우고, 나머지 컬럼은 결측값이 있는 행을 삭제해줘.”
pandas loc·iloc — 라벨 기반 vs 정수 기반 완전 정리
pandas 전처리에서 가장 많이 헷갈리는 부분이다. 핵심은 단순하다.
loc— 이름표(라벨)로 찾는다iloc— 번호표(정수 위치)로 찾는다
DataFrame에는 두 가지 주소 체계가 있다. 행과 열에 붙어있는 이름(라벨), 그리고 몇 번째인지를 나타내는 순서(정수). loc는 이름으로 찾고, iloc는 순서로 찾는다.
# loc: 라벨로 접근 (이름 기준)
df.loc['2025-01-03', 'temperature'] # 날짜와 컬럼명으로 접근
# iloc: 정수 위치로 접근 (순서 기준)
df.iloc[2, 0] # 3번째 행, 첫 번째 열
결정적으로 다른 점이 하나 더 있다. 범위를 지정할 때 loc는 끝값을 포함하고, iloc는 끝값을 포함하지 않는다.
| 구분 | 기준 | 끝값 포함 여부 |
|---|---|---|
loc | 라벨(이름) | ✅ 포함 |
iloc | 정수(순서) | ❌ 미포함 |
인덱스가 숫자일 때 특히 주의해야 한다. 인덱스가 5, 10, 15로 구성된 DataFrame에서 loc[5]는 이름표 5번을 찾는다. iloc[0]은 0번째 순서, 즉 첫 번째 행을 찾는다. loc[0]을 쓰면 이름표 0은 없으므로 에러가 난다. 에러가 나면 그나마 다행이다. 인덱스가 우연히 일치하는 숫자로 구성되어 있으면 엉뚱한 데이터가 조용히 나온다.
실무에서는 loc를 더 많이 쓴다. 날짜나 컬럼명처럼 이름이 있는 게 훨씬 직관적이기 때문이다. iloc는 첫 행, 마지막 행처럼 순서가 명확할 때 주로 쓴다.
AI 프롬프트 예시
“df에서 날짜 인덱스가 ‘2025-01-01’부터 ‘2025-01-07’까지인 행만, ‘A’와 ‘C’ 컬럼만 추출하는 코드 짜줘. loc를 써줘.”
조건 필터링과 데이터 수정
조건 필터링
원하는 조건에 맞는 행만 골라내는 게 조건 필터링이다. “A 컬럼 값이 0보다 큰 행만 뽑아라”, “특정 값이 목록에 포함된 행만 뽑아라” 같은 방식이다.
조건이 맞으면 해당 행이 포함되고, 맞지 않으면 제외된다. 여러 조건을 동시에 걸 수도 있다. 이때 AND 조건과 OR 조건을 혼동하지 않도록 조심해야 한다.
where() — numpy와 pandas는 반대다
where()는 numpy와 pandas에서 동작 방향이 반대다. 이걸 모르면 AI에게 요청할 때도 엉뚱한 결과가 나온다.
- numpy의 where — 조건이 True인 곳에 값1을, False인 곳에 값2를 넣는다
- pandas의 where — 조건이 False인 곳만 대체값으로 바꾼다. 조건을 만족하는 곳은 그대로 둔다
즉 pandas의 where는 “조건을 만족하지 않는 값을 바꿔라”는 개념이다. 조건을 만족하는 값을 바꾸고 싶다면 mask()를 쓴다.
데이터 수정
특정 위치의 값을 바꾸는 건 loc 또는 iloc로 해당 위치에 접근한 뒤 새 값을 대입하는 방식이다. 조건 기반으로 여러 값을 한 번에 바꾸는 것도 가능하다.
원본 보존 여부를 항상 의식해야 한다. 수정 작업 전에 df.copy()로 복사본을 만들어두면 실수해도 되돌릴 수 있다.
AI 프롬프트 예시
“df에서 ‘pressure’ 컬럼 값이 0보다 작은 행만 필터링해서 새 DataFrame으로 만들어줘. 원본 df는 건드리지 마.”
행·열 추가·삭제 완전 정리
열 추가
새로운 열을 추가할 때는 새 컬럼명에 데이터를 대입한다. 이때 추가하는 데이터의 행 수가 기존 DataFrame과 반드시 일치해야 한다. 길이가 다르면 오류가 난다.
행·열 삭제: drop()
drop()은 행 또는 열을 삭제하는 함수다. 행을 삭제할 때는 인덱스를 기준으로, 열을 삭제할 때는 컬럼명을 기준으로 지정한다.
df.drop('A', axis=1) # 'A' 컬럼 삭제 (axis=1이 열 기준)
drop()에서 가장 중요한 개념이 inplace다. inplace=True를 쓰지 않으면 원본은 바뀌지 않는다. 삭제 결과가 반환될 뿐이고, 원본 DataFrame은 그대로 남아있다. AI에게 요청할 때 “원본을 바꿔줘”인지 “복사본에서 작업해줘”인지를 명확히 전달해야 의도한 대로 코드가 나온다.
| 옵션 | 동작 |
|---|---|
inplace=False (기본값) | 원본 유지, 결과만 반환 |
inplace=True | 원본 직접 수정 |
원본을 보존하면서 작업하고 싶다면 먼저 df.copy()로 복사본을 만든 뒤 작업한다.
AI 프롬프트 예시
“df에서 ‘temp_flag’와 ‘unused’ 컬럼을 삭제해줘. 원본은 건드리지 말고 새 DataFrame으로 반환해줘.”
핵심 요약
| 단계 | 핵심 개념 | AI 요청 시 명시할 것 |
|---|---|---|
| 파일 입출력 | 형식·구분자·시트 지정 | 파일명, 시트명, 결측값 문자열, 인덱스 저장 여부 |
| 결측값 확인 | 컬럼별 현황 파악 | 확인 범위 (전체 / 특정 컬럼) |
| 결측값 처리 | 제거 vs 대체 판단 | 어떤 컬럼을 어떤 방식으로 처리할지 |
| 데이터 선택 | 라벨(loc) vs 정수(iloc) | 접근 기준이 이름인지 순서인지 |
| 수정·삭제 | inplace 여부, 원본 보존 | 원본 수정 여부, 복사본 사용 여부 |
pandas 전처리는 코드를 외우는 게 목적이 아니다. 어떤 처리가 필요한지 판단하고, 그 판단을 AI에게 정확하게 전달하는 게 핵심이다. 개념을 알면 프롬프트가 달라지고, 프롬프트가 달라지면 결과가 달라진다.
전처리에서 loc·iloc로 데이터를 꺼냈다면, 다음은 조건 기반 인덱싱과 불리언 필터링까지 AI에게 정확히 시키는 방법이다.
전처리 전에 DataFrame 자체의 구조와 생성 방법을 먼저 잡아두면 AI 요청 정확도가 달라진다.
pandas 전처리와 인덱싱을 더 깊이 공부하고 싶다면 pandas 공식 문서에서 직접 확인해볼 수 있다.







