실전 데이터 분석 66: 도심 행정지구별 인구 밀도 및 치안 순찰인력 수 대비 강력/일반 범죄지수 상관성 분석
📌 강의 개요 (30분 완성)

도심 치안 센터의 순찰관 배치 수와 인구 밀도 대비 지구별 범죄 수준 지수(CrimeRateIndex) 분석용 데이터셋입니다. 순찰 인력의 배치가 실제 거동 예방과 상관관계가 있는지 분석합니다.
학습 목표:
- 결측치 평균 대치 (
fillna): 치안센터별 순찰관 수 결측을 관할 지역 평균 순찰관 수로 대입하여 결측을 채웁니다. - 도시 범죄 유형 비교 (
barplot,scatterplot): 강력계 및 경절도 등 사건 유형별 평균 지수 막대 및 순찰 인력수 대비 범죄지수의 음의 선형 산점도를 도출합니다.
🧐 실무 도메인 지식 가이드 (Domain Knowledge Guide)
💰 금융 및 핀테크 (Finance & FinTech) 금융 데이터 분석은 자산의 리스크 관리(Credit Risk), 투자 자산 평가, 이상 금융 거래 감지(FDS) 등을 해결하기 위한 통계적 검정 분야입니다.
- 리스크와 대출 부도(Default): 대출 연체 여부나 투자 손실 위험은 금융 자산 건전성을 지키기 위해 고도화된 스코어링 모형으로 분석됩니다.
- 소득 대비 부채 비율(DTI): 개인이 갚을 수 있는 능력 한도를 객관적으로 판단하는 지표로 금융 신용 여신 관리의 핵심 척도입니다.
- 자산 변동성(Volatility): 주가나 크립토 시세의 표준편차는 위험 자산의 위험도를 계산(VaR)하고 투자 포트폴리오를 다변화하는 기준이 됩니다.
Step 1: 데이터 구조 살펴보기 (Data Overview)
csv_data 폴더에 준비해 둔 city_crimes.csv 파일을 판다스로 불러옵니다.
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 그래프 설정 (한글 폰트 및 마이너스 기호 깨짐 방지)
import koreanize_matplotlib
plt.rcParams['axes.unicode_minus'] = False
sns.set_theme(style="whitegrid")
# 로컬 CSV 파일 불러오기
df = pd.read_csv('./city_crimes.csv')
# 데이터 구조 및 첫 5행 확인
df = pd.read_csv('./city_crimes.csv')
print(df.info())
print(df.head())
💻 [실행 결과]
<class 'pandas.DataFrame'> RangeIndex: 1000 entries, 0 to 999 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 RecordID 1000 non-null int64 1 Neighborhood 1000 non-null str 2 CrimeType 1000 non-null str 3 PopulationDensity 1000 non-null float64 4 OfficerCount 987 non-null float64 5 CrimeRateIndex 1000 non-null float64 dtypes: float64(3), int64(1), str(2) memory usage: 63.9 KB None RecordID Neighborhood ... OfficerCount CrimeRateIndex 0 660001 District E ... 35.0 61.8 1 660002 District H ... 20.0 80.0 2 660003 District D ... 18.0 85.8 3 660004 District K ... 16.0 78.5 4 660005 District K ... 29.0 28.4 [5 rows x 6 columns]
<class ‘pandas.DataFrame’>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 6 columns):
# Column Non-Null Count Dtype
— —— ————– —–
0 RecordID 1000 non-null int64
1 Neighborhood 1000 non-null str
2 CrimeType 1000 non-null str
3 PopulationDensity 1000 non-null float64
4 OfficerCount 987 non-null float64
5 CrimeRateIndex 1000 non-null float64
dtypes: float64(3), int64(1), str(2)
memory usage: 47.0 KB
RecordID Neighborhood CrimeType PopulationDensity OfficerCount CrimeRateIndex
0 660001 District E Vandalism 7932.7 35.0 61.8
1 660002 District H Assault 3845.0 20.0 80.0
2 660003 District D Assault 2719.8 18.0 85.8
3 660004 District K Assault 1747.0 16.0 78.5
4 660005 District K Theft 4956.2 29.0 28.4
```
💡 코드 딥다이브 (Code Deep Dive)
주요 분석 대상 컬럼:
RecordID: 범죄 기록 식별 일련 번호Neighborhood: 관할 행정 지구명CrimeType: 접수된 범죄 사건 분류 (Theft, Assault, Vandalism 등)PopulationDensity: 지구 내 제곱킬로미터당 거주인구 밀도OfficerCount: 배치 근무하는 순찰 경찰관 수 (결측치 존재)CrimeRateIndex: 관할 지역의 가중치 적용 종합 범죄 지수 (10.0~100.0)
Step 2: 전처리와 결측치 정제 (Preprocess)
현실의 데이터는 항상 누락이 있거나 유효성 정제가 필요합니다. 데이터 전처리 단계에서 결측 상태를 확인하고 올바르게 보정합니다.
# 1. 컬럼별 결측치 개수 확인
print("--- 정제 전 결측치 확인 ---")
print(df.isnull().sum())
# 2. 결측치 전처리 및 대치 수행
mean_off = df['OfficerCount'].mean()
df['OfficerCount'] = df['OfficerCount'].fillna(mean_off)
print(df.isnull().sum())
💻 [실행 결과]
--- 정제 전 결측치 확인 --- RecordID 0 Neighborhood 0 CrimeType 0 PopulationDensity 0 OfficerCount 13 CrimeRateIndex 0 dtype: int64 RecordID 0 Neighborhood 0 CrimeType 0 PopulationDensity 0 OfficerCount 0 CrimeRateIndex 0 dtype: int64
— 정제 전 결측치 확인 — RecordID 0 Neighborhood 0 CrimeType 0 PopulationDensity 0 OfficerCount 13 CrimeRateIndex 0
— 정제 후 결측치 확인 — RecordID 0 Neighborhood 0 CrimeType 0 PopulationDensity 0 OfficerCount 0 CrimeRateIndex 0
```
💡 분석가의 통찰 (Analyst’s Insight)
- 치안 인력 보정의 실무 당위성: 행정 보고 누락 등으로 유실된 치안 요원 근무 데이터를 보정합니다. 치안센터별 경찰 근무 평균(약 26.5명)을 주입해 데이터 왜곡을 최소화하며 거시 치안 요율 분석 표본 크기를 온전히 유지합니다.
Step 3: 단변수 분포 분석 (Univariate EDA)
가장 먼저 핵심 변수가 전체 데이터에서 어떤 빈도와 분포를 가졌는지 단일 변수 시각화를 통해 파악해 봅니다.
plt.figure(figsize=(8, 5))
# 단변수 분석 그래프 생성
sns.barplot(data=df, x='CrimeType', y='CrimeRateIndex', palette='muted', errorbar=None)
plt.title('범죄 유형별 평균 범죄 지수', fontsize=14, fontweight='bold')
plt.show()
💻 [실행 결과]
💡 시각화 차트 읽는 법 & 인사이트
- 범죄 유형별 위험 지수 평균 분석: 폭행(Assault)이나 강력 사건 유형의 평균 범죄지수 막대가 기물파손(Vandalism)이나 단순절도(Theft) 등 경범죄 대비 월등히 높게 형성됩니다. 이는 지역 치안 위험도 측정 시 범죄 유형별 가중치를 부여해야 함을 시사합니다.
Step 4: 다변수 상관관계 및 이상치 분석 (Multivariate EDA)
두 개 이상의 변수를 동시에 결합하여, 조건에 따른 수치 차이나 독립 변수와 종속 변수 간의 통계적 경향을 분석합니다.
plt.figure(figsize=(9, 6))
# 다변수 분석 그래프 생성
sns.scatterplot(data=df, x='OfficerCount', y='CrimeRateIndex', color='red', alpha=0.7)
plt.title('배치 순찰 요원 수 대비 범죄 지수 분산', fontsize=14, fontweight='bold')
plt.show()
💻 [실행 결과]
💡 코드 딥다이브 & 비즈니스 통찰 (Analyst’s Insight)
- 치안 인력 밀도와 범죄 억제의 선형 음의 관계 규명: 산점도를 분석하면 배치 순찰 경찰관 수(X축)가 증가할수록 범죄율 인덱스(Y축)가 아래로 떨어지는 뚜렷한 반비례 상관 구도가 나타납니다. 즉, 상주 순찰 인력을 늘리는 것이 도심 치안의 선제 예방 효과에 기여함을 보장해 줍니다.
Step 5: 통계적 직관과 해석 (Statistical Logic)
💡 [음의 선형 상관관계와 치안 요율의 한계 체감 법칙] 데이터 분석에서 두 변수가 반대 방향으로 연동할 때 이를 음의 상관관계(Negative Correlation)라고 합니다.
- 이 산점도상에서 보듯 순찰관 수와 범죄지수는 강력한 음의 선형 기울기를 지닙니다.
- 다만 실무적으로는 순찰 대원을 무한정 투입한다고 범죄가 0으로 내려가진 않으며, 특정 임계점 이후에는 범죄율 하락 폭이 점차 둔화되는 ‘한계 효용 체감’이 일어납니다.
- 이를 OLS 비선형(로그/이차) 적합선으로 추가 검증하여 최적의 경찰 인력 효율 배치선을 산출합니다.
🎯 30분 강의 마무리 및 심화 과제
오늘 우리는 실전 데이터셋을 분석하여 판다스로 데이터를 가공 및 정제하고, 시각화를 활용하여 핵심 변수 간의 통계적 유의성을 검증했습니다. 데이터 속에서 숨겨진 패턴을 올바른 시각으로 탐색하는 능력이 데이터 사이언티스트의 가장 강력한 무기입니다.
📝 심화 과제 (Advanced Challenge)
- 인구 밀도(PopulationDensity)별 범죄지수의 상관계수 산출: 인구 밀도 수준과 범죄율 간의 상관성을 분석하여 인구 집중이 치안 악화에 유의하게 작용하는지 증명해 보세요.
- 고위험 치안 지구 리스크 요약: 범죄지수(
CrimeRateIndex)가 75를 초과하는 최고 위험 관할 지역 서브셋의 특징을 테이블로 추출하세요.