전 게시물에 이어서 서울시 범죄현황 통계자료를 가지고 어느 구가 범죄로부터 안전하고 또 위험한지 데이터 분석 및 시각화 실습을 진행해보겠습니다. 이번 게시물은 데이터 탐색부터 데이터 시각화까지입니다. 이전 데이터 분석 실습내용이 궁금하시다면 아래 게시물을 참고해주세요.
2024.11.25 - [python] - 파이썬 정형 데이터 분석 & 데이터 시각화 (with Jupyter Notebook, Pandas)(1)
파이썬 정형 데이터 분석 & 데이터 시각화 (with Jupyter Notebook, Pandas)(1)
이번 게시물에서는 서울시 관서별 5대 범죄 발생 & 검거 현황 데이터를 이용해 "어떤 구가 범죄율이 낮고 살기 좋은지" 알아 보기 위해 데이터를 분석하고 시각화하는 실습을 해보려고 합니다.
eunduun.tistory.com
데이터 탐색 (Data Exploration)
- 검거율 기준으로 오름차순 정렬하기
gu_df.sort_value(by='검거율', ascending=True, inplace=True)
ascending=False : 내림차순
inplace=True : 덮어쓰기
- 범죄별 발생 건수 정규화하기
5대 범죄별 수치를 해당 범죄별 최대값으로 나눠줘서 정규화를 진행해줍니다.
범죄별로 가장 많이 발생한 구가 1 == 100% 입니다.
weight_col = gu_df[['강간', '강도', '살인', '절도', '폭력']].max()
crime_count_norm = gu_df[['강간', '강도', '살인', '절도', '폭력']] / weight_col
하지만 인구 수가 고려되지 않은 최대 발생 건수를 기준으로 했기 때문에 잘 알 수 없습니다. 이후에 인구 수를 고려해서 살펴보겠습니다.
인구 대비 범죄 발생 비율 알아보기
인구 데이터 merge하기
정확한 위험도를 알기 위해 단순히 범죄건수만 보지 않고 인구수로 나눠서 인구대비 발생비율을 살펴보겠습니다.
1. 인구 데이터를 가져온 후 gu_df와 구별 index를 기준으로 merge 하기 위해 index를 세팅해줍니다.
popul_df = pd.read_csv('pop_kor.csv', encoding='utf-8', index_col='구별')
popul_df.head()
아래와 같이 먼저 read_csv()로 읽어들이고 .set_index()를 적용할 수도 있습니다.
popul_df = pd.read_csv('pop_kor.csv', encoding='utf-8').set_index('구별')
2. join()을 사용해 gu_df에 popul_df를 merge 해줍니다.
gu_df = gu_df.join(popul_df)
3. 구별 인구 수를 반영한 비율을 구한다.
범죄 수 비율을 구별 인구 수로 나눠준 후 인구 수 단위인 10만을 곱해줍니다.
행(구)별 범죄 수 비율 / 구별 인구 수 * 100000
crime_ratio = crime_count_norm.div(gu_df['인구수'], axis=0) * 100000
crime_ratio.head()
seaborn의 heatmap을 이용해 시각화하기
한글 데이터 시각화를 위해서 다음과 같은 코드를 넣어줍니다.
# jupyter notebook 내에 figure를 보여주기
%matplotlib inline
# matplotlib의 한글문제를 해결
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
# font_name
rc('font', family=font_name)
- 구별 살인 발생 순위 살펴보기
sns.heatmap(crime_count_norm.sort_values(by='살인', ascending=False)) # ascending=False : 내림차순
위의 코드는 crime_count_norm을 '살인' 열을 기준으로 내림차순 정렬하라는 뜻입니다.
코드를 실행해보면 다음과 같은 그래프가 나옵니다. 하지만 이 그래프에는 문제가 있습니다.
첫 번째로는 이 그래프를 보고는 정확한 수치를 알기 힘들다는 것이고, 수치가 작을 수록 짙은 색을 띄고 있어서 오해하기 쉽다는 것입니다.
두번째로는 항목들끼리 너무 다닥다닥 붙어있어서 잘 알아보기 힘듭니다.
따라서 이 문제를 해결하기 위해서 몇 가지 옵션을 주어서 수정해주도록 하겠습니다.
- 확인이 편리하도록 옵션 수정해주기
plt.figure(figsize = (10,10))
sns.heatmap(crime_count_norm.sort_values(by='살인', ascending=False), annot=True, fmt='f', linewidths=.5, cmap='Reds')
plt.title('범죄 발생(살인발생으로 정렬) - 각 항목별 최대값으로 나눠 정규화')
plt.show()
plt.figure() 함수를 이용해서 figure 사이즈를 조정해줄 수 있습니다.
다음으로 heatmap에 추가해준 옵션입니다.
annot : 셀 내에 수치 입력 여부
fmt : 셀 내에 입력될 수치의 format (f == float)
linewidth : 셀 간 이격거리(내부 테두리)
cmap : matpotlib colormap @ https://goo.gl/YWpBES <- 이 페이지에서 colormap을 확인하실 수 있습니다.
plt.title() 함수를 이용해서 제목도 정해줍니다.
실행 결과입니다. 보기 훨씬 편해진 모습입니다.
(다른 열 기준으로 살펴보시고 싶으시면 by='원하는 열이름' 으로 바꿔주시면 됩니다.)
이제 구별 5대 범죄 발생 수치의 평균을 구해 어떤 구가 모든 범죄에서 평균적으로 안전한지 알아보겠습니다.
- 구별 5대범죄 발생 수치 평균 / 순위 비교
crime_ratio['전체발생비율'] = crime_ratio.mean(axis=1)
plt.figure(figsize = (10,10))
sns.heatmap(crime_ratio.sort_values(by='전체발생비율', ascending=False), annot=True, fmt='f', linewidths=.5, cmap='Reds')
plt.title('범죄 발생(전체발생비율로 정렬) - 각 항목을 정규화한 후 인구로 나눔')
plt.show()
코드를 실행해보면 다음과 같은 실행결과가 나옵니다.
Folium library 을 활용한 geo-mapping
지도 시각화를 위해 파이썬에서 사용할 수 있는 Folium library를 활용하겠습니다.
Folium library를 설치해줍니다.
!pip install folium==0.5.0
https://github.com/southkorea/southkorea-maps
GitHub - southkorea/southkorea-maps: South Korea administrative divisions in ESRI Shapefile, GeoJSON and TopoJSON formats.
South Korea administrative divisions in ESRI Shapefile, GeoJSON and TopoJSON formats. - southkorea/southkorea-maps
github.com
southkorea github에서 서울만 따로 추린 GeoJSON 파일을 활용합니다.
1. GeoJSON 파일 가져오기
import json
geo_path = 'skorea_municipalities_geo_simple.json'
geo_str = json.load(open(geo_path, encoding='utf-8'))
여기서 가져온 geo_str은 dict 형식으로 아래와 같은 내용을 담고 있습니다.
2. Folium library를 활용해 지도 불러오기
import folium
map = folium.Map(location=[37.5502, 126.982], zoom_start=11, tiles='Cartodb Positron')
map
tiles : 지도 타입 (default type or "Stamen Terrain" or "Stamen Toner")
location : 초기 지도 center 위치
인구 수 대비 5대 범죄 발생 수치 평균 구별 시각화
map = folium.Map(location=[37.5502, 126.982], zoom_start=11, tiles='Cartodb Positron')
# 전체 5대 범죄 인구당 발생비율 시각화
map.choropleth(geo_data = geo_str,
data = crime_ratio['전체발생비율'],
columns = [crime_ratio.index, crime_ratio['전체발생비율']],
fill_color = 'PuRd', #PuRd, YlGnBu
key_on = 'feature.id')
map
map.choropleth()
: 지도에 데이터의 색상 차이를 시각화하는 함수입니다.
geo_data=geo_str
: GeoJSON 데이터를 입력해야 합니다. 각 구에 대한 경계 정보를 포함하는 GeoJSON 형식의 데이터를 참조합니다.
data=gu_df['검거율']
: gu_df라는 데이터프레임에서 '검거율' 열의 데이터를 사용합니다.
columns=[gu_df.index, gu_df['검거율']]
: gu_df의 인덱스(각 구의 이름)와 '검거율' 열을 시각화에 사용할 데이터로 설정합니다.
key_on='feature.id'
: GeoJSON 데이터에서 각 구의 ID를 기준으로 색을 입히려는 설정입니다.
다음은 시행 결과 입니다.
지금까지 파이썬을 이용해서 데이터를 전처리하고 탐색하고 시각화하는 실습을 진행해보았습니다.
앞으로 더 많은 데이터를 가지고 시각화해보도록 하겠습니다.
데이터 다루기 달인이 되는 그 날까지 화이팅입니다.
'python' 카테고리의 다른 글
[python]파이썬 정형 데이터 분석 & 데이터 시각화 (with Jupyter Notebook, Pandas)(1) (3) | 2024.11.25 |
---|