1. ์ฝ๋์ ๋ชฉ์ ๊ณผ ์ญํ ๋ถ์
์์ธ์ ๋๋ณ ์ธ๊ตญ์ธ ์ธ๊ตฌ ๋ฐ์ดํฐ๋ฅผ ์๊ฐ์ ์ผ๋ก ํํํ๋ ์ง๋ ๋จ๊ณ ๊ตฌ๋ถ๋ (Choropleth Map)๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ฃผ ๋ชฉ์
- ์์ธ์ ๋๋ณ ์ธ๊ตญ์ธ ์ธ๊ตฌ ๋ฐ์ง๋ ์๊ฐํ
- ์์ธ์ ๋ด ์ง์ญ๊ฐ ์ธ๊ตญ์ธ ์ธ๊ตฌ ๋ถํฌ ํํฉ ๋ถ์
- ์์ธ์ ๊ตฌ ๊ฒฝ๊ณ์ ์ ์ถ๊ฐํ์ฌ ์ง์ญ ๊ฐ ๋น๊ต ์ฉ์ด์ฑ ์ฆ๋
2. ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ์ ๋ฐ ์ญํ
pandas : ๋ฐ์ดํฐ ๋ก๋ฉ ๋ฐ ์ ์ฒ๋ฆฌ
json : GeoJSON ์ง๋ ๋ฐ์ดํฐ ๋ก๋ฉ -> ์์ธ์์ ๋๋ณ, ๊ตฌ๋ณ ๊ฒฝ๊ณ ๋ฐ์ดํฐ ๋ก๋ฉ
folium : ์ธํฐ๋ํฐ๋ธ ์ง๋ ์๊ฐํ
webbrowser : ์ง๋๋ฅผ ์น๋ธ๋ผ์ฐ์ ์์ ๋ฐ๋ก ์ด๊ธฐ
3. ์ฃผ์ ๊ธฐ๋ฅ ์ ๋ฆฌ
GeoJSON ๋ฐ์ดํฐ ์ฒ๋ฆฌ : ์์ธ์์ ๋๋ณ, ๊ตฌ๋ณ ๊ฒฝ๊ณ ๋ฐ์ดํฐ ๋ก๋ฉ
๋ฐ์ดํฐ ํ์ ๋ณํ : ํ์ ๊ตฌ์ญ ์ฝ๋ ์ผ์นํ (์ซ์ -> ๋ฌธ์)
๋จ๊ณ ๊ตฌ๋ถ๋ ์์ฑ : ์ธ๊ตญ์ธ ์ธ๊ตฌ ๋ฐ์ดํฐ๋ฅผ ์ง๋์ ์๊ฐ์ ํํ
์ถ๊ฐ ์ง๋ ์ ๋ณด : ์์ธ์ ๊ตฌ ๊ฒฝ๊ณ์ ์ถ๊ฐ
4. ์ฝ๋ ๋ฏ์ด๋ณด๊ธฐ
import pandas as pd # ๋ฐ์ดํฐ ๋ก๋ฉ ๋ฐ ์ฒ๋ฆฌ
import json # GeoJSON ํ์ผ ์ฒ๋ฆฌ
import folium # ์ง๋ ์๊ฐํ
import webbrowser # ๋ธ๋ผ์ฐ์ ์์ ์ง๋ ์ด๊ธฐ
๋ฐ์ดํฐ ๋ถ์์ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ import
def browser_open(f_map, path):
html_page = f'{path}' # ์ ์ฅํ HTML ํ์ผ ์ด๋ฆ ์ง์
f_map.save(html_page) # ์ง๋ ๊ฐ์ฒด๋ฅผ HTML๋ก ์ ์ฅ
webbrowser.open(html_page) # ์ ์ฅ๋ HTML ํ์ผ ๋ธ๋ผ์ฐ์ ์์ ์ด๊ธฐ
์ง๋ ์๋ ์ด๊ธฐ ํจ์ ์ ์
geo_seoul = json.load(open("assets/EMD_Seoul.geojson", encoding="utf-8"))
foreigner = pd.read_csv("assets/Foreigner_EMD_Seoul.csv")
GeoJSON ๋ฐ์ดํฐ ๋ก๋ฉ
์์ธ์ ๋ ๊ฒฝ๊ณ ์ขํ ๋ก๋ฉ, csv ํ์ผ๋ก ์ธ๊ตญ์ธ ์ธ๊ตฌ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ฉ
foreigner["code"] = foreigner["code"].astype(str)
ํ์ ๊ตฌ์ญ ์ฝ๋ ์ปฌ๋ผ์ GeoJSON ๋ฐ์ดํฐ์ ์ผ์น์ํค๊ธฐ ์ํด ๋ฌธ์์ด๋ก ๋ณํ
bins = list(foreigner["pop"].quantile([0, 0.2, 0.4, 0.6, 0.7, 0.8, 0.9, 1]))
๊ณ๊ธ ๊ตฌ๊ฐ (bins) ์ค์ : ๋ฐ์ดํฐ๋ฅผ ๋ฐฑ๋ถ์์๋ก ๋๋ ์ธ๋ถ์ ์ผ๋ก ํํ
map_seoul = folium.Map(
location=[37.56, 127], # ์ง๋ ์ค์ฌ (์์ธ ์ค์ฌ๋ถ)
zoom_start=12, # ๋ ๊ฒฝ๊ณ๋ฅผ ์ ๋ํ๋ผ ํ๋ ์์ค
tiles="cartodbpositron" # ์ง๋ ์คํ์ผ (๊น๋ํ ๋์์ธ)
)
folium.Choropleth(
geo_data=geo_seoul,
data=foreigner,
columns=("code", "pop"),
key_on="feature.properties.ADM_DR_CD",
fill_color="Blues",
nan_fill_color="White",
fill_opacity=1, # ํฌ๋ช
๋(์คํ์์ )
line_opacity=0.5, # ๊ฒฝ๊ณ์ ํฌ๋ช
๋(์คํ์์ )
bins=bins
).add_to(map_seoul)
์ง๋ ์์ฑ + ๋จ๊ณ ๊ตฌ๋ถ๋ (๋ ๋จ์ ์ธ๊ตญ์ธ ์ธ๊ตฌ) ์๊ฐํ
- ๋๋ณ ์ธ๊ตญ์ธ ์ธ๊ตฌ ๋ฐ์ดํฐ๋ฅผ ํ๋์ ๋จ๊ณ๋ก ํํ
- ๋ฐ์ดํฐ ๋๋ฝ๋ ์ง์ญ์ ํฐ์์ผ๋ก ํ์
geo_seoul_sig = json.load(open("assets/SIG_Seoul.geojson", encoding="utf-8"))
folium.Choropleth(
geo_data=geo_seoul_sig,
fill_opacity=0, # ์์ญ ๋ด๋ถ๋ ํฌ๋ช
line_weight=4 # ๊ฒฝ๊ณ์ ๊ตต๊ฒ ํํ
).add_to(map_seoul)
์์ธ์ ๊ตฌ ๊ฒฝ๊ณ์ ์ถ๊ฐ
- ์ถ๊ฐ์ ์ธ ๊ตฌ ๋จ์ ๊ฒฝ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ฉ
- ๊ตฌ ๊ฒฝ๊ณ์ ์ ์ถ๊ฐํ์ฌ ๋ช ํํ ์ง์ญ ๊ฒฝ๊ณ๋ฅผ ํ์ํจ์ผ๋ก์จ ์ง๋ ๊ฐ๋ ์ฑ์ ์ฆ๊ฐ์ํด
browser_open(map_seoul, "geo3.html")
์์ฑ๋ ์ง๋๋ฅผ html๋ก ์ ์ฅํ๊ณ ๋ฐ๋ก ๋ธ๋ผ์ฐ์ ์ ํ์ (ํจ์ ์ ์ธํด๋ )
5. ๋ถ์์ ์ธ์ฌ์ดํธ ๋์ถ ๋ฐฉ์
1. ์ธ๊ตญ์ธ ๋ฐ์ง ์ง์ญ ํ์
- ๋ ๋จ์ ์ธ๊ตฌ์ ์ฐจ์ด๋ฅผ ํ์ธํ๊ณ , ๋ฐ์ง์ง์ญ๊ณผ ๋ฎ์ ์ง์ญ์ ์ ์ฑ ์ ์ ๊ทผ์ด ๊ฐ๋ฅ
2. ํ์ ์๋น์ค ์ง์ ํ์ ์ง์ญ ์ ์
- ๋ค๋ฌธํ ์ง์์ผํฐ๋ ์ธ๊ตญ์ธ์ ์ํ ์๋น์ค ์์น ์ ์ ์ ์ ์ฉ
3. ์๊ฐ์ ๋ฐ๋ฅธ ์ธ๊ตญ์ธ ์ธ๊ตฌ ๋ณํ
- ์ฐ๋๋ณ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด ์ธ๊ตฌ ๋ณํ ํธ๋ ๋ ๋ถ์ ๊ฐ๋ฅ
6. ์ถ๊ฐ ํ
1. ์์ฃผ ์ฐ์ด๋ ๋ฐ์ดํฐ ์๊ฐํ ๋ฐฉ๋ฒ ํ์คํ
- GeoJSON ๋ฐ์ดํฐ์ pandas dataframe ์ฐ๊ฒฐ ๋ฐฉ์์ ์ฝ๋ ์ค๋ํซ์ผ๋ก ๊ด๋ฆฌํด ํจ์จ์ฑ ํฅ์
2. ์ธํฐ๋ํฐ๋ธ ์์ ์ถ๊ฐ
folium Toolip์ ์ถ๊ฐํ์ฌ ๋๋ณ ์ธ๊ตฌ ์๋ฅผ ๋ง์ฐ์ค ์ค๋ฒ ์ ํ์ธ ๊ฐ๋ฅํ๊ฒ ์ค์ (์ฌ์ฉ์ ํธ์์ฑ)
folium.GeoJson(
geo_seoul,
tooltip=folium.GeoJsonTooltip(fields=["ADM_DR_NM", "ADM_DR_CD"])
).add_to(map_seoul)