- 강남3구 범죄현황 데이터 개요 및 읽어오기
- [번외1] Pandas의 pivot_table
- 서울시 범죄현황 데이터 정리
- google maps에서 구별 정보를 얻어서 데이터 정리
- 구별 데이터로 변경하기
- 서울시 범죄현황 데이터 최종 정리
- [번외2] seaborn
- 범죄 현황 데이터 시각화
- [번외3] Folium 지도 시각화 <- here
- 서울시 범죄 현황 지도 시각화
Folium은 지도 위에 데이터를 표현하여 시각화하는 도구이다.
지난 시간에 구글맵에서 위도, 경도 정보를 가져오는 법을 배웠으므로
이젠 그렇게 받은 위치 정보를 이용해 지도 시각화를 할 수 있다~
!pip install folium
!pip install charset
!pip install charset-normalizer
필요한 모듈 import
import folium
import pandas as pd
import json
location에 위도와 경도 좌표를 넣어주고
zoom_start로 화면상 노출되는 사이즈를 조절해준다.
위도, 경도는 구글맵에서 찾을 수 있는데...
상세 위치를 클릭하여 주소창에서 보이는 숫자값들이 좌표이다(난 이렇게 눈빠지게 찾았다 왜 나만 좌표 정보가 잘 안보이는 건가)
m = folium.Map(location=[37.3925126, 126.6393808], zoom_start=17)
m
지도가 생겼다~
m.save("./folium.html") # 현재 경로에 파일 저장
# 지도를 웹에서 확인 가능
지도에 마커를 생성해주는 기능이다.
공원 두 곳을 지정하여 마크를 표시해주었다.
popup <- 클릭하면 보이는 내용 지정
tooltip <- 마우스를 올리기만 해도 보이는 내용, 문구에는 html 문법을 적용할 수 있다.
링크 연결하는 문법도 적용 가능하다.
m = folium.Map(
location=[37.3925126, 126.6393808],
zoom_start=14,
)
# 센트럴파크
folium.Marker(
(37.3925126, 126.6393808),
popup="<a href='https://www.insiseol.or.kr/park/songdo/facility/central.jsp' target=_'blink'>Songdo central park</a>"
).add_to(m)
# 달빛축제공원
folium.Marker(
(37.4064278, 126.6338237),
popup="Moonlight festival park",
tooltip="Park"
).add_to(m)
m
마커에 다양한 아이콘으로 정보를 좀 더 줄 수 있다.
여러 옵션들로 아이콘을 커스텀할 수 있다.
https://getbootstrap.com/docs/3.3/components/
https://fontawesome.com/search?m=free&o=r
등의 웹사이트를 참고하면 좋다.
m = folium.Map(
location=[37.3925126, 126.6393808],
zoom_start=14,
)
# 센트럴파크
folium.Marker(
(37.3925126, 126.6393808),
popup="<a href='https://www.insiseol.or.kr/park/songdo/facility/central.jsp' target=_'blink'>Songdo central park</a>",
icon=folium.Icon(
color="red",
icon_color="pink",
icon="cloud"
)
).add_to(m)
# 달빛축제공원
folium.Marker(
(37.4064278, 126.6338237),
popup="Moonlight festival park",
tooltip="Park",
icon=folium.Icon(color="black")
).add_to(m)
m
지도 위에 마우스로 클릭했을 때 마커를 생성해주는 기능이다.
팝업 기능으로 위도와 경도 정보를 보여주었다
m = folium.Map(
location=[37.3925126, 126.6393808],
zoom_start=17
)
m.add_child(folium.ClickForMarker())
-> 클릭하면 마커 생성됨
지도를 마우스로 클릭했을 때 위도, 경도 정보를 반환해주는 기능이다.
m = folium.Map(
location=[37.3925126, 126.6393808],
zoom_start=17
)
m.add_child(folium.LatLngPopup())
요러케 내가 클릭한 곳에 정보가 나옴
유용하게 쓰일듯한 circle 기능.
m = folium.Map(
location=[37.3925126, 126.6393808],
zoom_start=17
)
# Circle
folium.Circle(
location=[37.3925126, 126.6393808],
radius=100,
fill=True,
color="red",
fill_color="red"
).add_to(m)
m
choropleth map은 색상을 활용하여 지도상에서 요소들의 차이를 나타내는 지도인데,
배포받은 us_unemployment 자료를 활용하여
미국 지도 위에 실업율을 그려보자
import json
state_data = pd.read_csv("../data/02. US_Unemployment_Oct2012.csv")
state_data.tail()
이러케 state, unemployment rate 두 가지의 정보가 있는 데이터프레임이다.
data로는 json파일 경로를 입력해주었다.
이 파일은 경계선 좌표값이 담긴 데이터이다.
51개의 행이 있는 데이터인데 행 하나당 state의 정보가 담겨있고, 좌표값이 있다.
가장 먼저 folium.Map으로 밑바탕이 되는 지도를 만들어주고,
geo_data로 json형태로 경계선 좌표값 데이터가 있기 때문에 경계선을 그어주고
데이터를 불러와 실업율이 높으면 진하게, 낮으면 연하게 시각화가 되도록 값을 넣어준다.
m = folium.Map([43, -102], zoom_start=3)
folium.Choropleth(
geo_data="../data/02. us-states.json", # 경계선 좌표값이 담긴 데이터
data=state_data, # Series or DataFrame
columns=["State", "Unemployment"],
key_on="feature.id",
fill_color="BuPu",
fill_opacity=1, # color 투명도 0-1
line_opacity=0.5, # line 투명도 0-1
legend_name="Unemployment rate (%)"
).add_to(m)
m
한 눈에 실업율을 비교할 수 있는 미국 지도가 완성되었다~~
이젠 서울 지도에다가 범죄 현황 자료를 가지고 시각화할 것이다.
우리나라 경계선 데이터에서 서울 부분만 추려 저장하여 로드해주었다.
[출처] https://github.com/southkorea/southkorea-maps
crime_gu_norm = pd.read_csv(
"../data/02. crime_in_Seoul_final.csv", index_col=0, encoding="utf-8"
)
geo_path = "../data/02. skorea_municipalities_geo_simple.json"
geo_str = json.load(open(geo_path, encoding="utf-8"))
서울 지역 지도 생성해주고,
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11
)
이제 다양한 주제에 대하여 지도 시각화를 할 것이다.
folium.Choropleth(
geo_data=geo_str, # 우리나라 경계선 좌표값이 담긴 데이터
data=crime_gu_norm["살인"],
columns=[crime_gu_norm.index, crime_gu_norm["살인"]], # index<- 구 이름
key_on="feature.id",
fill_color="PuRd",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="정규화된 살인 발생 건수"
).add_to(my_map)
my_map
영등포구가 가장 많네 ㄷㄷ
folium.Choropleth(
geo_data=geo_str,
data=crime_gu_norm["강간"],
columns=[crime_gu_norm.index, crime_gu_norm["강간"]],
key_on="feature.id",
fill_color="PuRd",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="정규화된 강간 발생 건수"
).add_to(my_map)
my_map
강남3구 중 2개 구가 포함이네 ㄷㄷ
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11
)
folium.Choropleth(
geo_data=geo_str,
data=crime_gu_norm["범죄"],
columns=[crime_gu_norm.index, crime_gu_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_gu_norm["범죄"] / crime_gu_norm["인구수"]
folium.Choropleth(
geo_data=geo_str,
data=tmp_criminal,
columns=[crime_gu_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
강남 범죄 발생 건수 높네.
이런 식으로 대략적인 정보를 한 눈에 파악할 수 있다!
이제 경찰서 위치도 마커로 표시하여
합체해보자!!
경찰서의 능력을 보여주는 지도라 할 수 있다.
어떤 경찰서가 검거를 잘하는지??등의 분석을 할 수 있다.
먼저 경찰서 위치 정보 데이터 불러오기 - 경찰서별 위도/경도를 구글맵 이용하여 for문으로 불러왔던 자료이다.
crime_station_gu = pd.read_csv(
"../data/02. crime_in_Seoul_1st.csv", encoding="utf-8"
)
검거 컬럼 생성,
axis=1은 행(가로) 을 뜻한다. 가로로 검거 컬럼들을 연산한 평균값을 넣어준 것이다.
numpy에서 axis=1은 행(가로), pandas에서 axis=1은 열(세로) 을 뜻함!!
col = ["살인검거", "강도검거", "강간검거", "절도검거", "폭력검거"]
tmp = crime_station_gu[col] / crime_station_gu[col].max() # 0-1사이의 정규화
crime_station_gu["검거"] = np.mean(tmp, axis=1)
경찰서 위치 마커는 for문 찍었다.
이 때 iterrows를 사용한다.
인덱스와 행을 받아서, 행에서 lat과 lng를 찍어서 표시!
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11
)
for idx, rows in crime_station_gu.iterrows():
folium.Marker(
location=[rows["lat"], rows["lng"]]
).add_to(my_map)
my_map
여기에 경계선 데이터를 추가하고, 검거율에 따른 circle marker를 추가해보자.
circle marker의 크기는 radius와 검거 컬럼을 이용한다. 검거율이 높을수록 bigger circle이 되는 형식이다.
검거율에 적절한 값을 곱해주어 원이 잘 보이게 한다.
my_map = folium.Map(
location=[37.5502, 126.982],
zoom_start=11
)
folium.Choropleth(
geo_data=geo_str,
data=crime_gu_norm["범죄"],
columns=[crime_gu_norm.index, crime_gu_norm["범죄"]],
key_on="feature.id",
fill_color="PuRd",
fill_opacity=0.7,
line_opacity=0.2,
legend_name="정규화된 5대 범죄 발생 건수"
).add_to(my_map)
for idx, rows in crime_station_gu.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
Q. 강남, 송파, 서초 정말 안전한 것입니까?
-> 범죄 발생 건수가 결코 낮지 않고, 범죄 검거율 또한 높지는 않다.
안전<-이라는 것 자체에 대해서는
정말 여러가지 요소를 고려해야 하는 게 맞긴 하지만.
또한 범죄는 많은데 검거는 잘함, 범죄 없고 검거도 잘함,
범죄율에 비해 검거율 낮은 구,
...등등의 정보를 알 수 있다.
.
.
.
지도 시각화 재밌다