자료를 검토한 결과, 모든 지도를 SVG 하나로 처리하기보다 데이터 유형별로 맞는 방식을 나누는 것이 가장 정확합니다. 행정구역 단위 데이터는 경계 지도, 위도·경도 데이터는 점 지도로 시각화합니다.
데이터를 불러오는 중입니다…
경계 출처: Wikimedia Commons 행정구역 SVG 및 southkorea/seoul-maps GeoJSON. 데이터 출처: Wikidata SPARQL(P1082 인구, P2046 면적), GeoJSON 속성값. 출처 상세는 assets/*.SOURCE.txt에 기록했습니다.
데이터를 불러오는 중입니다…
| 유형 | 사용 자료 | 원본/출처 | 수업 포인트 |
|---|---|---|---|
| 전국 광역시도 경계 | skorea_provinces_geo_simple.json | southkorea/southkorea-maps · KOSTAT 센서스 경계 기반 | 경계 파일의 지역명과 통계 CSV의 지역명을 매칭 |
| 서울 구 경계 | seoul_municipalities_geo_simple.json | southkorea/seoul-maps · KOSTAT 2013 | 25개 구가 모두 1:1로 매칭되는지 확인 |
| 서울 동 경계 | seoul_neighborhoods_geo_simple.json | southkorea/seoul-maps · JUSO 2015 | 동 단위는 명칭·개편 이력이 있어 매칭 전처리가 중요 |
| 인구/면적 | seoul_district_wikidata_population.csv, korea_sido_wikidata_population.csv | Wikidata SPARQL P1082/P2046. 공식 인구 수업 확장은 행정안전부 주민등록 인구통계 권장 | 출처별 최신성·공식성·재현성을 비교 |
| 위치점 데이터 | 지진, 병원, 자전거, 생물종 등 위경도 CSV | 각 데이터셋 상세 페이지의 공식 API 링크 | 경계 데이터가 아니라 좌표 데이터이므로 점 지도가 적합 |
주의: 현재 인구 CSV는 키 없이 재현 가능한 공개 지식그래프 샘플입니다. 공식 행정 수업에서는 행정안전부 주민등록 인구통계 CSV를 내려받아 같은 열 이름으로 바꾸면 동일 코드로 교체할 수 있습니다.
import pandas as pd
pop = pd.read_csv("https://thinkervis.github.io/free-api-data-science-edu/data/seoul_district_wikidata_population.csv")
print(pop.head())
print("구 개수:", pop["district"].nunique())
# 수업 질문: 인구밀도가 가장 높은 구와 낮은 구는?
print(pop.sort_values("population_density_per_km2", ascending=False)[["district", "population_density_per_km2"]].head())
print(pop.sort_values("population_density_per_km2")[["district", "population_density_per_km2"]].head())
import pandas as pd
import plotly.express as px
url = "https://thinkervis.github.io/free-api-data-science-edu/data/korea_sido_wikidata_population.csv"
df = pd.read_csv(url)
fig = px.bar(df.sort_values("population"), x="population", y="region", orientation="h",
title="전국 광역시도별 인구")
fig.show()
const rows = await fetch("../data/seoul_district_wikidata_population.csv")
.then(r => r.text())
.then(parseCsvRows)
.then(toObjects);
// 핵심: 경계 파일의 properties.name과 CSV의 district가 같아야 색칠 가능
const rowByDistrict = Object.fromEntries(rows.map(r => [r.district, r]));
const value = Number(rowByDistrict["강남구"].population_density_per_km2);