Project 2 - 서울시 범죄 현황 데이터 분석 (5)
서울시 범죄 현황에 대한 지도 시각화
crime_anal_norm.tail(2)
| 살인 | 강도 | 강간 | 절도 | 폭력 | 강간검거율 | 강도검거율 | 살인검거율 | 절도검거율 | 폭력검거율 | 인구수 | CCTV | 범죄 | 검거 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 구별 | ||||||||||||||
| 중구 | 0.214286 | 0.205128 | 0.383721 | 0.585671 | 0.407957 | 74.747475 | 87.5 | 100.0 | 42.511628 | 89.707865 | 134593 | 1023 | 0.359353 | 78.893394 |
| 중랑구 | 0.571429 | 0.358974 | 0.317829 | 0.460637 | 0.580125 | 91.463415 | 100.0 | 87.5 | 62.211709 | 85.714286 | 412780 | 916 | 0.457799 | 85.377882 |
살인발생 건수 지도 시각화
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11,
tiles="Stamen Toner"
)
folium.Choropleth(
geo_data=geo_str, # 우리나라 경계선 좌표값이 담긴 데이터
data=crime_anal_norm["살인"],
columns=[crime_anal_norm.index, crime_anal_norm["살인"]],
key_on="feature.id",
fill_color="PuRd",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="정규화된 살인 발생 건수"
).add_to(my_map)
my_map

성범죄 건수 지도 시각화
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11,
tiles="Stamen Toner"
)
folium.Choropleth(
geo_data=geo_str, # 우리나라 경계선 좌표값이 담긴 데이터
data=crime_anal_norm["강간"],
columns=[crime_anal_norm.index, crime_anal_norm["강간"]],
key_on="feature.id",
fill_color="PuRd",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="정규화된 강간 발생 건수"
).add_to(my_map)
my_map

5대 범죄 건수 지도 시각화
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11,
tiles="Stamen Toner"
)
folium.Choropleth(
geo_data=geo_str, # 우리나라 경계선 좌표값이 담긴 데이터
data=crime_anal_norm["범죄"],
columns=[crime_anal_norm.index, crime_anal_norm["범죄"]],
key_on="feature.id",
fill_color="PuRd",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="정규화된 5대 범죄 발생 건수"
).add_to(my_map)
my_map

인구 대비 범죄 발생 건수
tmp_criminal = crime_anal_norm["범죄"] / crime_anal_norm["인구수"]
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11,
tiles="Stamen Toner"
)
folium.Choropleth(
geo_data=geo_str, # 우리나라 경계선 좌표값이 담긴 데이터
data=tmp_criminal,
columns=[crime_anal_norm.index, tmp_criminal],
key_on="feature.id",
fill_color="PuRd",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="인구 대비 범죄 발생 건수"
).add_to(my_map)
my_map

경찰서별 정보 범죄발생과 함께 정리
crime_anal_station = pd.read_csv(
"../data/02. crime_in_Seoul_1st.csv", encoding="utf-8"
)
crime_anal_station.tail(2)
| 구분 | 강간검거 | 강간발생 | 강도검거 | 강도발생 | 살인검거 | 살인발생 | 절도검거 | 절도발생 | 폭력검거 | 폭력발생 | 구별 | lat | lng | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 29 | 29 | 중부 | 96.0 | 141.0 | 3.0 | 3.0 | 2.0 | 2.0 | 485.0 | 1204.0 | 1164.0 | 1335.0 | 중구 | 37.563646 | 126.989580 |
| 30 | 30 | 혜화 | 64.0 | 101.0 | 6.0 | 6.0 | 2.0 | 2.0 | 379.0 | 988.0 | 842.0 | 972.0 | 종로구 | 37.571840 | 126.998856 |
col = ["살인검거", "강도검거", "강간검거", "절도검거", "폭력검거"]
tmp = crime_anal_station[col] / crime_anal_station[col].max() # 정규화
crime_anal_station["검거"] = np.mean(tmp, axis=1) # numpy axis=1 : 행(가로), pandas axis=1 : 열(세로)
crime_anal_station.tail(2)
| 구분 | 강간검거 | 강간발생 | 강도검거 | 강도발생 | 살인검거 | 살인발생 | 절도검거 | 절도발생 | 폭력검거 | 폭력발생 | 구별 | lat | lng | 검거 | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 29 | 29 | 중부 | 96.0 | 141.0 | 3.0 | 3.0 | 2.0 | 2.0 | 485.0 | 1204.0 | 1164.0 | 1335.0 | 중구 | 37.563646 | 126.989580 | 0.277182 |
| 30 | 30 | 혜화 | 64.0 | 101.0 | 6.0 | 6.0 | 2.0 | 2.0 | 379.0 | 988.0 | 842.0 | 972.0 | 종로구 | 37.571840 | 126.998856 | 0.240065 |
경찰서 위치 마커 표시
my_map = folium.Map(
location=[37.5502, 126.982], zoom_start=11
)
for idx, rows in crime_anal_station.iterrows():
folium.Marker(
location=[rows["lat"], rows["lng"]]
).add_to(my_map)
my_map

경찰서 검거율 원에 적용
my_map = folium.Map(
location=[37.5502, 126.982], zoom_start=11
)
folium.Choropleth(
geo_data=geo_str,
data=crime_anal_norm["범죄"],
columns=[crime_anal_norm.index, crime_anal_norm["범죄"]],
key_on="feature.id",
fill_color="PuRd",
fill_opacity=0.7,
line_opacity=0.2,
).add_to(my_map)
for idx, rows in crime_anal_station.iterrows():
folium.CircleMarker(
location=[rows["lat"], rows["lng"]],
radius=rows["검거"] * 50,
popup=rows["구분"] + " : " + "%.2f" % rows["검거"],
color="#3186cc",
fill=True,
fill_color="#3186cc"
).add_to(my_map)
my_map

서울시 범죄 현황 발생 장소 분석
추가 검증
crime_loc_raw = pd.read_csv(
"../data/02. crime_in_Seoul_location.csv", thousands=",", encoding="euc-kr"
)
crime_loc_raw.tail(2)
| 범죄명 | 장소 | 발생건수 | |
|---|---|---|---|
| 63 | 폭력 | 금융기관 | 42 |
| 64 | 폭력 | 기타 | 26382 |
crime_loc_raw.범죄명.unique()
=>
array(['살인', '강도', '강간.추행', '절도', '폭력'], dtype=object)
---------------------------------------------------------------
crime_loc_raw["장소"].unique()
=>
array(['아파트, 연립 다세대', '단독주택', '노상', '상점', '숙박업소, 목욕탕', '유흥 접객업소', '사무실',
'역, 대합실', '교통수단', '유원지 ', '학교', '금융기관', '기타'], dtype=object)
--------------------------------------------------------------------------------------------------
crime_loc = crime_loc_raw.pivot_table(
crime_loc_raw, index="장소", columns="범죄명", aggfunc=[np.sum]
)
crime_loc.columns = crime_loc.columns.droplevel([0, 1])
crime_loc.tail(2)
| 범죄명 | 강간.추행 | 강도 | 살인 | 절도 | 폭력 |
|---|---|---|---|---|---|
| 장소 | |||||
| 유흥 접객업소 | 398 | 13 | 8 | 2035 | 2645 |
| 학교 | 33 | 0 | 0 | 400 | 203 |
col = ["살인", "강도", "강간", "절도", "폭력"]
crime_loc_norm = crime_loc / crime_loc.max() # 정규화
crime_loc_norm.head()
| 범죄명 | 강간.추행 | 강도 | 살인 | 절도 | 폭력 |
|---|---|---|---|---|---|
| 장소 | |||||
| 교통수단 | 0.324718 | 0.000000 | 0.000000 | 0.021027 | 0.008415 |
| 금융기관 | 0.000940 | 0.011494 | 0.015385 | 0.049738 | 0.001592 |
| 기타 | 1.000000 | 0.770115 | 1.000000 | 1.000000 | 1.000000 |
| 노상 | 0.463346 | 1.000000 | 0.338462 | 0.429235 | 0.929990 |
| 단독주택 | 0.185620 | 0.172414 | 0.461538 | 0.103110 | 0.135661 |
crime_loc_norm["종합"] = np.mean(crime_loc_norm, axis=1)
crime_loc_norm.tail(2)
| 범죄명 | 강간.추행 | 강도 | 살인 | 절도 | 폭력 | 종합 |
|---|---|---|---|---|---|---|
| 장소 | ||||||
| 유흥 접객업소 | 0.187030 | 0.149425 | 0.123077 | 0.093632 | 0.100258 | 0.130684 |
| 학교 | 0.015508 | 0.000000 | 0.000000 | 0.018404 | 0.007695 | 0.008321 |
장소별 범죄 발생 장소
crime_loc_norm_sort = crime_loc_norm.sort_values("종합", ascending=False) # 내림차순
def drawGraph():
plt.figure(figsize=(10, 10))
sns.heatmap(
crime_loc_norm_sort,
annot=True,
fmt="f",
linewidths=0.5,
cmap="RdPu")
plt.title("범죄 발생 장소")
plt.show()
drawGraph()
