매달 출동 현황을 손으로 집계하는 일은 반복적이고 실수가 잦습니다. 이 안내서는 출동 기록 CSV 한 장으로 월별·유형별·요일×시간대·지역별 집계와 차트 4종, 보고용 엑셀까지 만드는 방법입니다. 외부 AI API를 쓰지 않는 순수 집계라 로그인·키가 필요 없습니다.
이 안내서를 끝내면 출동 CSV를 pandas로 집계하고, 집계 합이 전체 행 수와 맞는지 자동 검산해 "옮겨적기 오류"를 잡을 수 있습니다.
필요한 것 — 표준 컬럼 4개
출동 기록에서 네 개의 컬럼만 있으면 됩니다.
reported_at— 신고/출동 일시incident_type— 출동 유형district— 지역 단위(행정동 등)incident_id— 중복 제거·검산용 고유값
부서마다 컬럼명이 다르면 매핑 한 줄로 맞춥니다.
PYTHON
COLUMN_MAP = {
"신고일시": "reported_at",
"사고유형": "incident_type",
"행정동": "district",
}
집계 4종
날짜에서 월·요일·시간대를 뽑고, 네 가지로 집계합니다.
PYTHON
df["일시"] = pd.to_datetime(df["reported_at"]) df["월"] = df["일시"].dt.month df["요일"] = df["일시"].dt.dayofweek.map(dict(enumerate("월화수목금토일"))) df["시간대"] = df["일시"].dt.hour monthly = df.groupby("월").size().rename("건수") by_type = df["incident_type"].value_counts().rename("건수") heat = (df.pivot_table(index="요일", columns="시간대", values="incident_id", aggfunc="count", fill_value=0).reindex(list("월화수목금토일"))) top_dong = df["district"].value_counts().head(10).rename("건수")
이렇게 월별 추이, 유형별 구성, 요일×시간대 히트맵, 지역 TOP10 — 네 가지 표와 차트가 나옵니다.
검산: 집계 합 = 전체 행 수
보고서 숫자가 틀리면 신뢰를 잃습니다. 그래서 집계가 끝나면 합이 전체 행 수와 같은지 확인하고, 다르면 멈춥니다.
PYTHON
# 검산: 집계의 합 = 전체 행 수 (다르면 멈추고 사람이 본다) assert monthly.sum() == len(df) == by_type.sum(), "검산 실패: 집계 합이 전체 행 수와 다릅니다" print(f"[검산] 월별 합 {monthly.sum():,} = 유형 합 {by_type.sum():,} = 전체 {len(df):,} ✓")
▸ 소방 활용 포인트
이 한 줄(assert)이 월말 집계의 "옮겨적기 오류"를 자동으로 잡습니다. 합성 데이터와 실데이터를 보고서에 함께 쓸 때는 어느 쪽인지 반드시 표시하세요.숫자를 문장으로 옮길 때 — 단정 금지
집계 결과를 문장으로 옮길 때, AI에게 표에 없는 원인·평가를 만들지 말라고 못박습니다.
TEXT
아래 표는 합성 또는 승인된 집계표입니다. 표에 없는 원인, 평가, 책임 소재를 만들지 않도록 요청합니다. 각 문장 끝에 검산할 숫자 또는 확인할 원문 항목을 붙여 달라고 요청합니다. 공식 판단처럼 보이는 표현은 "추가 확인 필요"로 바꿔 달라고 요청합니다.
경계는 분명합니다. "합성 데이터 기준 3월 건수가 다른 월보다 많습니다"는 괜찮지만 "3월에 실제 위험이 증가했습니다"는 안 됩니다. "해당 집계 단위에서 건수가 높게 나타납니다"는 괜찮지만 "위험지역입니다"는 안 됩니다.
사람 검토 체크리스트
TEXT
- [ ] 개인정보 열을 제거한 뒤 실행했습니다. - [ ] 검산 출력이 입력 행 수와 일치합니다. - [ ] 튀는 수치는 원자료에서 다시 확인했습니다. - [ ] 보고서에 넣을 때 합성 데이터와 실데이터를 혼동하지 않도록 표시했습니다.
⚠️ 흔한 실수
동봉 예제 데이터는 합성 데이터입니다 — 현실 통계가 아닙니다. 실제 데이터로 돌릴 때는 개인정보 열을 먼저 제거하세요.