Data Analysis

์„œ์šธ์‹œ ๋™๋ณ„ ์™ธ๊ตญ์ธ ์ธ๊ตฌ ๋ฐ์ดํ„ฐ ์‹œ๊ฐํ™”, Choropleth Map, folium, webbrower, pandas, json

๊น€์‹ฌ์Šจ 2025. 6. 1. 15:19

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)