본문 바로가기
/ 학습 / 안내서 / 데이터 처리
L1 입문 · 11분 읽기

지저분한 출동 데이터 깔끔하게 정제하기

2026.07.12 갱신 엑셀 이상의 데이터를 다뤄야 하는 실무자
#데이터처리#전처리#입문
검토 상태: 전문 검토 전 위험도 미분류

이 안내서는 공식 절차·법령·현장 판단을 대체하지 않으며, 적용 전 소속 기관 기준과 담당자 검토를 확인하세요.

분석 업무의 절반 이상은 데이터를 다듬는 일입니다. 출동 기록처럼 사람이 손으로 입력한 데이터는 빈 칸·중복·표기 흔들림이 섞여 있어, 그대로 집계하면 숫자가 틀립니다. 이 안내서는 지저분한 CSV 한 장을 분석 가능한 깨끗한 표로 만드는 순서를 따라갑니다.

🎯 이 장의 목표
  • 표의 행·열·키가 업무에서 무엇을 뜻하는지 설명할 수 있습니다.
  • 결측·중복·표기 불일치를 구분해 처리 방법을 선택할 수 있습니다.
  • 원본을 보존한 채 정제 규칙을 순서대로 적용할 수 있습니다.
  • 정제 전후의 행 수와 값 분포를 비교해 결과를 검산할 수 있습니다.

배경지식

CSV와 엑셀 표는 서류철을 일정한 칸으로 나눈 것과 같습니다. 한 은 출동이나 점검 같은 기록 한 건이고, 한 은 시각·유형·관할처럼 모든 기록에 공통으로 묻는 항목입니다. 이 약속이 흔들리면 같은 열에 날짜와 메모가 섞이고, 집계 도구는 무엇을 세어야 할지 판단하지 못합니다.

기록을 서로 구별하는 값은 입니다. 출동번호처럼 한 건을 가리키는 키가 있으면 중복을 찾을 수 있지만, 이름이나 주소처럼 바뀌거나 겹치는 값만으로는 같은 건인지 확정하기 어렵습니다. 키가 없을 때는 여러 열을 함께 보고 사람이 원자료를 확인해야 합니다.

빈 칸인 결측값은 숫자 0과 다릅니다. 0은 측정한 결과가 없다는 값이고, 빈 칸은 측정하지 않았거나 입력이 빠졌다는 상태일 수 있습니다. 정제는 이 차이를 보존하면서, 같은 뜻의 표기를 한 형태로 맞추는 정규화와 중복 판정을 순서대로 적용하는 일입니다.

왜 지저분한 데이터가 숫자를 틀리게 하는가

정제 방법을 배우기 전에, 왜 이 일이 필요한지부터 봅니다. 데이터 정제는 창고에서 재고를 세기 전에 물건 이름표를 맞추는 일과 같습니다. 같은 생수인데 누구는 "생수", 누구는 "생 수", 누구는 "먹는샘물"이라고 적어 두면, 재고 시스템은 이걸 세 종류로 세어 버립니다. 실제로는 하나인데 숫자가 셋으로 쪼개지는 것입니다.

집계 도구도 똑같이 동작합니다. pandas의 집계는 글자가 정확히 같은 값끼리만 묶습니다. "강서구"와 "강서"는 사람 눈엔 같은 곳이지만 컴퓨터에겐 서로 다른 글자입니다. 그래서 표기가 흔들린 채로 관할서별 건수를 세면, 한 관할서의 출동이 여러 줄로 흩어져 순위가 뒤바뀝니다.

빈 칸과 중복도 같은 방식으로 숫자를 흔듭니다. 출동시각이 빈 줄을 그대로 두면 "언제"를 묻는 집계에서 조용히 빠지고, 같은 출동이 두 줄로 들어와 있으면 건수가 부풀려집니다. 정제는 숫자를 예쁘게 만드는 일이 아니라, 숫자가 사실과 맞게 만드는 일입니다.

가상 상황: 관할서 1위가 뒤바뀐 월말 집계

가상의 상황을 하나 들어 보겠습니다. 월말에 관할서별 출동 건수를 뽑아 상급자에게 보고해야 합니다. 집계표를 보니 1위가 예상과 다릅니다. 원자료를 열어 보니 한 관할서 이름이 이렇게 흩어져 있습니다(아래 숫자는 예시입니다).

TEXT
강서구      1,203
강서           88
강서소방서       5

세 줄은 모두 같은 관할서입니다. 그런데 집계는 이걸 세 곳으로 세어, 1,296건이어야 할 관할서가 1,203건으로 낮게 잡히고 순위가 밀렸습니다. 표기 하나 때문에 보고서의 결론이 바뀐 것입니다. 이런 어긋남은 눈으로는 잘 안 보이고, 아래 절의 value_counts() 같은 도구로만 드러납니다. 그래서 정제의 첫 걸음은 고치는 것이 아니라 보는 것입니다.

가상 사례: 예방 점검 내역의 빈 상태값 분리하기

다음은 실제 시설이나 점검 결과가 아닌 가상 사례입니다. 예방업무 담당자는 두 프로그램에서 내보낸 합성 점검 CSV를 하나로 합쳐 재확인이 필요한 행을 추리려 합니다. 한 파일은 시설 식별자 앞뒤에 공백이 있고, 다른 파일은 점검 상태가 빈 행과 미입력인 행이 섞여 있습니다.

담당자는 먼저 원본 두 파일을 복사해 보존하고, 각 열의 결측 수와 식별자 빈도를 확인합니다. 식별자는 앞뒤 공백만 제거하되, 상태가 빈 행을 임의로 정상이나 미점검으로 채우지 않습니다. 빈 상태는 별도의 확인 후보로 분리하고, 합친 뒤에는 원본 행 수와 중복 제거 수를 기록합니다.

공백 정리 전에 합치면 같은 시설이 두 건처럼 보이고, 빈 상태를 임의로 채우면 실제 점검 여부를 단정하게 됩니다. 결과는 처분 명단이 아니라 원자료 재확인 목록입니다. 담당자는 시설 식별자와 점검 원장을 대조한 뒤 상태를 확정합니다.

먼저, 손대기 전에 살펴본다

정제의 첫 단계는 코드가 아니라 관찰입니다. 무엇이 문제인지 모르고 고칠 수는 없습니다. 의사가 처방 전에 문진과 검사를 하듯, 코드로 고치기 전에 데이터의 상태부터 읽는 것입니다.

PYTHON
import pandas as pd
df = pd.read_csv("dispatch.csv")

df.shape                      # (행, 열) — 전체 규모
df.info()                     # 자료형·결측 개수
df.isna().sum()               # 열별 빈 칸 수
df["관할서"].value_counts()   # 표기 흔들림 발견

value_counts() 는 "강서구 1,203 / 강서 88 / 강서소방서 5"처럼 표기 불일치를 한눈에 드러냅니다.

네 줄이 각각 무엇을 알려주는지 짚어 보겠습니다.

  • df.shape — 전체 행·열 수. 내가 받은 데이터가 예상한 규모인지 먼저 확인합니다.
  • df.info() — 열마다 자료형과 결측 개수. 숫자여야 할 열이 문자로 읽혔는지 여기서 드러납니다.
  • df.isna().sum() — 열별 빈 칸 수. 어느 열을 손봐야 할지 알려줍니다.
  • value_counts() — 한 열에 어떤 값이 몇 번 나오는지. 표기 흔들림이 여기서 튀어나옵니다.

결측값: 버릴지 채울지 정한다

빈 칸을 무조건 채우는 게 아닙니다. 열의 의미로 결정합니다.

  • 핵심 키가 비면 버린다: 출동시각이 없으면 그 줄은 집계 불가 → 제거
  • 선택 정보면 표시한다: 비고가 비면 "미기재"로 채워 의미를 보존
PYTHON
df = df.dropna(subset=["출동시각"])        # 핵심 결측 → 행 제거
df["비고"] = df["비고"].fillna("미기재")   # 선택 결측 → 표시

예를 들어 출동시각이 빈 3줄은 dropna로 빠지고, 비고가 빈 20줄은 "미기재"로 남습니다. 앞의 3줄은 "언제"를 묻는 집계에서 빼야 정확하고, 뒤의 20줄은 남겨야 "비고를 안 적었다"는 사실이 보존됩니다. 같은 빈 칸이라도 처리가 정반대인 이유입니다.

⚠️ 흔한 실수
결측을 평균이나 0으로 무심코 채우면 통계가 왜곡됩니다. "왜 비었는지"를 먼저 생각하세요. 빈 값에는 대개 이유가 있습니다.

중복: 같은 출동이 여러 줄

  • 완전 중복: 모든 칸이 같은 줄 → 그대로 제거
  • 부분 중복: 같은 출동인데 일부 칸만 다름 → 키 컬럼으로 판정
PYTHON
df = df.drop_duplicates()                                   # 완전 중복
df = df.drop_duplicates(subset=["출동번호"], keep="first")  # 출동번호 기준

완전 중복은 시스템이 같은 기록을 두 번 저장했을 때 생기고, 부분 중복은 한 출동을 여러 담당자가 조금씩 다르게 입력했을 때 생깁니다. 후자는 모든 칸이 같지 않으므로 drop_duplicates()만으로는 안 걸립니다. "무엇이 같으면 같은 출동인가"를 정하는 키 컬럼(예: 출동번호)이 있어야 판정할 수 있습니다.

두 번째 줄은 충돌을 찾아 주는 코드가 아니라 이미 남길 행을 정했다는 전제에서 한 행만 고르는 코드입니다. 실행 순서는 다음과 같습니다.

  1. 먼저 df[df.duplicated(subset=["출동번호"], keep=False)]로 같은 번호의 모든 행을 펼쳐 값이 다른지 사람이 확인합니다.
  2. 값이 모두 같으면(완전 중복) 위 keep="first" 줄을 실행해 한 행만 남깁니다.
  3. 값이 다르면(부분 중복) 이 줄을 실행하지 않고, 최신 시각·승인 상태 같은 기관 기준과 원자료를 사람이 대조한 뒤 병합·보존·제외를 직접 결정합니다.

표기 통일: 하나의 이름으로

같은 대상을 다르게 적은 것을 합칩니다. 공백 제거가 먼저, 그다음 매핑입니다.

PYTHON
df["관할서"] = df["관할서"].str.strip()            # 앞뒤 공백 제거
매핑 = {"강서": "강서구", "강서소방서": "강서구"}
df["관할서"] = df["관할서"].replace(매핑)

이 두 줄이 실제로 무엇을 하는지 앞뒤를 비교하면 분명합니다. 정제 전에는 같은 관할서가 셋으로 흩어져 있습니다.

TEXT
강서구      1,203
강서           88
강서소방서       5

strip() 으로 앞뒤 공백을 없애고 매핑으로 이름을 하나로 모으면, 세 줄이 한 줄로 합쳐집니다.

TEXT
강서구      1,296

앞 절의 가상 상황에서 뒤바뀌었던 순위가 이제 제자리를 찾습니다. 규칙이 많아지면 매핑을 코드가 아니라 별도 표(CSV)로 빼두면 유지·검토가 쉽습니다.

마지막은 검산

정제는 반드시 전후를 비교해 의도대로 됐는지 확인합니다. 이 한 줄이 "조용한 실수"를 막습니다.

PYTHON
before = len(pd.read_csv("dispatch.csv"))
print("정제 전:", before, "행")
print("정제 후:", len(df), "행")
print("제거됨:", before - len(df), "행")

줄어든 행 수가 예상과 크게 다르면 규칙을 의심하세요. 멀쩡한 데이터를 지웠을 수 있습니다. 정제가 무서운 이유는 실수해도 오류 메시지가 안 나기 때문입니다 — 코드는 조용히 성공하고, 지워진 행은 아무도 눈치채지 못한 채 보고서에서 빠집니다. 검산은 그 침묵을 깨는 알람입니다.

자주 하는 실수

정제 단계에서 반복적으로 나오는 실수를 고친 방법과 나란히 두면 차이가 분명해집니다.

흔한 실수무엇이 문제인가대신
결측을 0이나 평균으로 일괄 채움없는 값을 있는 값으로 바꿔 통계가 왜곡됨열의 의미로 버릴지(dropna)·표시할지(fillna) 정함
표기 통일 없이 바로 집계같은 대상이 여러 줄로 쪼개져 순위·합계가 틀림strip → 매핑으로 이름을 하나로
검산 없이 결과를 보고조용히 지워진 행을 아무도 모름정제 전후 행 수를 비교
원본 파일을 덮어써 저장잘못 지우면 되돌릴 수 없음원본은 그대로 두고 정제본을 새 파일로 저장

마지막 실수는 특히 아픕니다. 원본을 덮어쓰면 규칙이 틀렸을 때 되돌릴 길이 없습니다. 원본 CSV는 손대지 말고, 정제 결과는 df.to_csv("dispatch_clean.csv", index=False) 처럼 새 이름으로 저장하는 습관을 들이세요.

정제가 끝나면

깨끗해진 표는 이제 집계로 넘어갈 준비가 됐습니다. 정제는 그 자체가 목적이 아니라, 믿을 수 있는 숫자를 만들기 위한 준비 단계입니다.

pandas 자체를 더 익히려면 pandas 코스를 따라가 보세요.

▸ 소방 활용 포인트
정제 규칙(어떤 열을 어떻게 처리했는지)을 주석이나 별도 문서로 남기면, 다음 사람이 같은 데이터를 다시 만질 때 시간을 크게 아끼고 집계 결과의 신뢰도가 올라갑니다.

용어 한 줄 사전

용어한 줄 설명
표에서 출동·점검 같은 기록 한 건을 나타내는 가로줄입니다.
모든 기록에 공통으로 저장하는 시각·유형 같은 항목입니다.
각 기록을 구별하거나 다른 표와 연결하는 기준값입니다.
결측값값이 0인 것이 아니라 기록되지 않았거나 알 수 없는 상태입니다.
중복같은 업무 사건이 둘 이상의 행으로 들어간 상태입니다.
정규화같은 뜻의 표기와 형식을 비교 가능한 한 형태로 맞추는 작업입니다.

자주 묻는 질문

Q. 빈 칸은 모두 지워도 되나요?

아닙니다. 핵심 키가 비어 분석할 수 없는 행과, 비고처럼 비어 있음 자체가 정보인 열은 다르게 다뤄야 합니다. 열의 업무 의미를 먼저 적고 처리 규칙을 정합니다.

Q. 중복은 첫 행만 남기면 되나요?

두 행 가운데 어느 것이 최신·정확한지 모르면 자동으로 첫 행을 고르면 안 됩니다. 완전 중복만 제거하고, 값이 다른 부분 중복은 원자료와 담당 기록을 확인합니다.

Q. 정제한 파일로 원본을 덮어써도 되나요?

원본은 그대로 보존하고 새 파일명으로 저장합니다. 그래야 규칙이 잘못됐을 때 처음부터 다시 검산하고, 어떤 행이 바뀌었는지 설명할 수 있습니다.

Q. 표기가 비슷하면 자동으로 합쳐도 되나요?

철자가 비슷하다는 이유만으로 같은 대상이라고 단정할 수 없습니다. 승인된 매핑표나 고유 키가 있을 때 합치고, 나머지는 사람이 확인할 후보로 남깁니다.

핵심 정리

  • 행·열·키의 업무 의미를 먼저 확인한 뒤 정제 규칙을 정합니다.
  • 결측값은 0과 다르며 빈 이유에 따라 제거·표시·확인을 선택합니다.
  • 표기 통일과 중복 제거는 승인된 키·매핑 기준으로 수행합니다.
  • 원본을 보존하고 전후 행 수와 값 분포를 비교해야 정제가 끝납니다.

다음 단계