Project 8 - 인구 소멸 위기 지역 데이터 분석
1. 배경
목표
- 인구 소멸 위기 지역 파악
- 인구 소멸 위기 지역 지도 표현
- 지도 표현에 대한 카르토그램 표현
2. 데이터 읽고 인구 소멸 지역 계산
requirements
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
import set_matplotlib_hangul
import warnings
matplotlib.rcParams['axes.unicode_minus'] = False
warnings.filterwarnings(action="ignore")
%matplotlib inline
fillna()
datas = {
"A": np.random.randint(1, 45, 8),
"B": np.random.randint(1, 45, 8),
"C": np.random.randint(1, 45, 8)
}
fillna_df = pd.DataFrame(datas)
fillna_df
| A | B | C | |
|---|---|---|---|
| 0 | 10 | 38 | 3 |
| 1 | 26 | 8 | 18 |
| 2 | 24 | 34 | 20 |
| 3 | 21 | 14 | 39 |
| 4 | 24 | 38 | 30 |
| 5 | 42 | 37 | 8 |
| 6 | 15 | 25 | 5 |
| 7 | 13 | 2 | 3 |
fillna_df.loc[2:4, ["A"]] = np.nan
fillna_df.loc[3:5, ["B"]] = np.nan
fillna_df.loc[4:7, ["C"]] = np.nan
fillna_df
| A | B | C | |
|---|---|---|---|
| 0 | 10.0 | 38.0 | 3.0 |
| 1 | 26.0 | 8.0 | 18.0 |
| 2 | NaN | 34.0 | 20.0 |
| 3 | NaN | NaN | 39.0 |
| 4 | NaN | NaN | NaN |
| 5 | 42.0 | NaN | NaN |
| 6 | 15.0 | 25.0 | NaN |
| 7 | 13.0 | 2.0 | NaN |
fillna_df.fillna(method="ffill") # pad
| A | B | C | |
|---|---|---|---|
| 0 | 10.0 | 38.0 | 3.0 |
| 1 | 26.0 | 8.0 | 18.0 |
| 2 | 26.0 | 34.0 | 20.0 |
| 3 | 26.0 | 34.0 | 39.0 |
| 4 | 26.0 | 34.0 | 39.0 |
| 5 | 42.0 | 34.0 | 39.0 |
| 6 | 15.0 | 25.0 | 39.0 |
| 7 | 13.0 | 2.0 | 39.0 |
데이터 불러오기
population = pd.read_excel("../data/07_population_raw_data.xlsx", header=1)
population.fillna(method="pad", inplace=True)
population
| 행정구역(동읍면)별(1) | 행정구역(동읍면)별(2) | 항목 | 계 | 20 - 24세 | 25 - 29세 | 30 - 34세 | 35 - 39세 | 65 - 69세 | 70 - 74세 | 75 - 79세 | 80 - 84세 | 85 - 89세 | 90 - 94세 | 95 - 99세 | 100+ | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 전국 | 소계 | 총인구수 (명) | 51696216.0 | 3541061.0 | 3217367.0 | 3517868 | 4016272.0 | 2237345.0 | 1781229.0 | 1457890 | 909130.0 | 416164.0 | 141488.0 | 34844 | 17562.0 |
| 1 | 전국 | 소계 | 남자인구수 (명) | 25827594.0 | 1877127.0 | 1682988.0 | 1806754 | 2045265.0 | 1072395.0 | 806680.0 | 600607 | 319391.0 | 113221.0 | 32695.0 | 7658 | 4137.0 |
| 2 | 전국 | 소계 | 여자인구수 (명) | 25868622.0 | 1663934.0 | 1534379.0 | 1711114 | 1971007.0 | 1164950.0 | 974549.0 | 857283 | 589739.0 | 302943.0 | 108793.0 | 27186 | 13425.0 |
| 3 | 서울특별시 | 소계 | 총인구수 (명) | 9930616.0 | 690728.0 | 751973.0 | 803507 | 817467.0 | 448956.0 | 350580.0 | 251961 | 141649.0 | 66067.0 | 24153.0 | 7058 | 5475.0 |
| 4 | 서울특별시 | 소계 | 남자인구수 (명) | 4876789.0 | 347534.0 | 372249.0 | 402358 | 410076.0 | 211568.0 | 163766.0 | 112076 | 54033.0 | 19595.0 | 6146.0 | 1900 | 1406.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 841 | 제주특별자치도 | 제주시 | 남자인구수 (명) | 235977.0 | 17377.0 | 13118.0 | 15084 | 18350.0 | 8474.0 | 6782.0 | 4941 | 2737.0 | 854.0 | 226.0 | 53 | 17.0 |
| 842 | 제주특별자치도 | 제주시 | 여자인구수 (명) | 234688.0 | 15261.0 | 12245.0 | 14687 | 18062.0 | 9265.0 | 7877.0 | 7178 | 5649.0 | 3122.0 | 1387.0 | 460 | 137.0 |
| 843 | 제주특별자치도 | 서귀포시 | 총인구수 (명) | 170932.0 | 10505.0 | 8067.0 | 9120 | 11606.0 | 8686.0 | 7460.0 | 6456 | 4521.0 | 1855.0 | 733.0 | 242 | 77.0 |
| 844 | 제주특별자치도 | 서귀포시 | 남자인구수 (명) | 86568.0 | 5600.0 | 4247.0 | 4693 | 6082.0 | 4237.0 | 3441.0 | 2611 | 1494.0 | 370.0 | 103.0 | 29 | 9.0 |
| 845 | 제주특별자치도 | 서귀포시 | 여자인구수 (명) | 84364.0 | 4905.0 | 3820.0 | 4427 | 5524.0 | 4449.0 | 4019.0 | 3845 | 3027.0 | 1485.0 | 630.0 | 213 | 68.0 |
population.info()
=>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 846 entries, 0 to 845
Data columns (total 16 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 행정구역(동읍면)별(1) 846 non-null object
1 행정구역(동읍면)별(2) 846 non-null object
2 항목 846 non-null object
3 계 846 non-null float64
4 20 - 24세 846 non-null float64
5 25 - 29세 846 non-null float64
6 30 - 34세 846 non-null int64
7 35 - 39세 846 non-null float64
8 65 - 69세 846 non-null float64
9 70 - 74세 846 non-null float64
10 75 - 79세 846 non-null int64
11 80 - 84세 846 non-null float64
12 85 - 89세 846 non-null float64
13 90 - 94세 846 non-null float64
14 95 - 99세 846 non-null int64
15 100+ 846 non-null float64
dtypes: float64(10), int64(3), object(3)
memory usage: 105.9+ KB
컬럼 이름 변경
population.rename(
columns={
"행정구역(동읍면)별(1)": "광역시도",
"행정구역(동읍면)별(2)": "시도",
"계": "인구수"
}, inplace=True
)
population.head()
| 광역시도 | 시도 | 항목 | 인구수 | 20 - 24세 | 25 - 29세 | 30 - 34세 | 35 - 39세 | 65 - 69세 | 70 - 74세 | 75 - 79세 | 80 - 84세 | 85 - 89세 | 90 - 94세 | 95 - 99세 | 100+ | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 전국 | 소계 | 총인구수 (명) | 51696216.0 | 3541061.0 | 3217367.0 | 3517868 | 4016272.0 | 2237345.0 | 1781229.0 | 1457890 | 909130.0 | 416164.0 | 141488.0 | 34844 | 17562.0 |
| 1 | 전국 | 소계 | 남자인구수 (명) | 25827594.0 | 1877127.0 | 1682988.0 | 1806754 | 2045265.0 | 1072395.0 | 806680.0 | 600607 | 319391.0 | 113221.0 | 32695.0 | 7658 | 4137.0 |
| 2 | 전국 | 소계 | 여자인구수 (명) | 25868622.0 | 1663934.0 | 1534379.0 | 1711114 | 1971007.0 | 1164950.0 | 974549.0 | 857283 | 589739.0 | 302943.0 | 108793.0 | 27186 | 13425.0 |
| 3 | 서울특별시 | 소계 | 총인구수 (명) | 9930616.0 | 690728.0 | 751973.0 | 803507 | 817467.0 | 448956.0 | 350580.0 | 251961 | 141649.0 | 66067.0 | 24153.0 | 7058 | 5475.0 |
| 4 | 서울특별시 | 소계 | 남자인구수 (명) | 4876789.0 | 347534.0 | 372249.0 | 402358 | 410076.0 | 211568.0 | 163766.0 | 112076 | 54033.0 | 19595.0 | 6146.0 | 1900 | 1406.0 |
소계 제거
population = population[population["시도"] != "소계"]
population.head()
| 광역시도 | 시도 | 항목 | 인구수 | 20 - 24세 | 25 - 29세 | 30 - 34세 | 35 - 39세 | 65 - 69세 | 70 - 74세 | 75 - 79세 | 80 - 84세 | 85 - 89세 | 90 - 94세 | 95 - 99세 | 100+ | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 6 | 서울특별시 | 종로구 | 총인구수 (명) | 152737.0 | 11379.0 | 11891.0 | 10684 | 10379.0 | 7411.0 | 6636.0 | 5263 | 3104.0 | 1480.0 | 602.0 | 234 | 220.0 |
| 7 | 서울특별시 | 종로구 | 남자인구수 (명) | 75201.0 | 5620.0 | 6181.0 | 5387 | 5034.0 | 3411.0 | 3009.0 | 2311 | 1289.0 | 506.0 | 207.0 | 89 | 73.0 |
| 8 | 서울특별시 | 종로구 | 여자인구수 (명) | 77536.0 | 5759.0 | 5710.0 | 5297 | 5345.0 | 4000.0 | 3627.0 | 2952 | 1815.0 | 974.0 | 395.0 | 145 | 147.0 |
| 9 | 서울특별시 | 중구 | 총인구수 (명) | 125249.0 | 8216.0 | 9529.0 | 10332 | 10107.0 | 6399.0 | 5313.0 | 4127 | 2502.0 | 1260.0 | 469.0 | 158 | 160.0 |
| 10 | 서울특별시 | 중구 | 남자인구수 (명) | 62204.0 | 4142.0 | 4792.0 | 5192 | 5221.0 | 3113.0 | 2405.0 | 1752 | 929.0 | 414.0 | 132.0 | 56 | 51.0 |
population.is_copy = False # copy 했을 때 warning X
population.rename(
columns={"항목": "구분"}, inplace=True
)
population.head()
| 광역시도 | 시도 | 구분 | 인구수 | 20 - 24세 | 25 - 29세 | 30 - 34세 | 35 - 39세 | 65 - 69세 | 70 - 74세 | 75 - 79세 | 80 - 84세 | 85 - 89세 | 90 - 94세 | 95 - 99세 | 100+ | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 6 | 서울특별시 | 종로구 | 총인구수 (명) | 152737.0 | 11379.0 | 11891.0 | 10684 | 10379.0 | 7411.0 | 6636.0 | 5263 | 3104.0 | 1480.0 | 602.0 | 234 | 220.0 |
| 7 | 서울특별시 | 종로구 | 남자인구수 (명) | 75201.0 | 5620.0 | 6181.0 | 5387 | 5034.0 | 3411.0 | 3009.0 | 2311 | 1289.0 | 506.0 | 207.0 | 89 | 73.0 |
| 8 | 서울특별시 | 종로구 | 여자인구수 (명) | 77536.0 | 5759.0 | 5710.0 | 5297 | 5345.0 | 4000.0 | 3627.0 | 2952 | 1815.0 | 974.0 | 395.0 | 145 | 147.0 |
| 9 | 서울특별시 | 중구 | 총인구수 (명) | 125249.0 | 8216.0 | 9529.0 | 10332 | 10107.0 | 6399.0 | 5313.0 | 4127 | 2502.0 | 1260.0 | 469.0 | 158 | 160.0 |
| 10 | 서울특별시 | 중구 | 남자인구수 (명) | 62204.0 | 4142.0 | 4792.0 | 5192 | 5221.0 | 3113.0 | 2405.0 | 1752 | 929.0 | 414.0 | 132.0 | 56 | 51.0 |
population.loc[population["구분"] == "총인구수 (명)", "구분"] = "합계"
population.loc[population["구분"] == "남자인구수 (명)", "구분"] = "남자"
population.loc[population["구분"] == "여자인구수 (명)", "구분"] = "여자"
population.head()
| 광역시도 | 시도 | 구분 | 인구수 | 20 - 24세 | 25 - 29세 | 30 - 34세 | 35 - 39세 | 65 - 69세 | 70 - 74세 | 75 - 79세 | 80 - 84세 | 85 - 89세 | 90 - 94세 | 95 - 99세 | 100+ | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 6 | 서울특별시 | 종로구 | 합계 | 152737.0 | 11379.0 | 11891.0 | 10684 | 10379.0 | 7411.0 | 6636.0 | 5263 | 3104.0 | 1480.0 | 602.0 | 234 | 220.0 |
| 7 | 서울특별시 | 종로구 | 남자 | 75201.0 | 5620.0 | 6181.0 | 5387 | 5034.0 | 3411.0 | 3009.0 | 2311 | 1289.0 | 506.0 | 207.0 | 89 | 73.0 |
| 8 | 서울특별시 | 종로구 | 여자 | 77536.0 | 5759.0 | 5710.0 | 5297 | 5345.0 | 4000.0 | 3627.0 | 2952 | 1815.0 | 974.0 | 395.0 | 145 | 147.0 |
| 9 | 서울특별시 | 중구 | 합계 | 125249.0 | 8216.0 | 9529.0 | 10332 | 10107.0 | 6399.0 | 5313.0 | 4127 | 2502.0 | 1260.0 | 469.0 | 158 | 160.0 |
| 10 | 서울특별시 | 중구 | 남자 | 62204.0 | 4142.0 | 4792.0 | 5192 | 5221.0 | 3113.0 | 2405.0 | 1752 | 929.0 | 414.0 | 132.0 | 56 | 51.0 |
소멸지역 조사를 위한 데이터
population["20-39세"] = (
population["20 - 24세"] +
population["25 - 29세"] +
population["30 - 34세"] +
population["35 - 39세"]
)
population["65세이상"] = (
population["65 - 69세"] +
population["70 - 74세"] +
population["75 - 79세"] +
population["80 - 84세"] +
population["85 - 89세"] +
population["90 - 94세"] +
population["95 - 99세"] +
population["100+"]
)
population.tail()
| 광역시도 | 시도 | 구분 | 인구수 | 20 - 24세 | 25 - 29세 | 30 - 34세 | 35 - 39세 | 65 - 69세 | 70 - 74세 | 75 - 79세 | 80 - 84세 | 85 - 89세 | 90 - 94세 | 95 - 99세 | 100+ | 20-39세 | 65세이상 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 841 | 제주특별자치도 | 제주시 | 남자 | 235977.0 | 17377.0 | 13118.0 | 15084 | 18350.0 | 8474.0 | 6782.0 | 4941 | 2737.0 | 854.0 | 226.0 | 53 | 17.0 | 63929.0 | 24084.0 |
| 842 | 제주특별자치도 | 제주시 | 여자 | 234688.0 | 15261.0 | 12245.0 | 14687 | 18062.0 | 9265.0 | 7877.0 | 7178 | 5649.0 | 3122.0 | 1387.0 | 460 | 137.0 | 60255.0 | 35075.0 |
| 843 | 제주특별자치도 | 서귀포시 | 합계 | 170932.0 | 10505.0 | 8067.0 | 9120 | 11606.0 | 8686.0 | 7460.0 | 6456 | 4521.0 | 1855.0 | 733.0 | 242 | 77.0 | 39298.0 | 30030.0 |
| 844 | 제주특별자치도 | 서귀포시 | 남자 | 86568.0 | 5600.0 | 4247.0 | 4693 | 6082.0 | 4237.0 | 3441.0 | 2611 | 1494.0 | 370.0 | 103.0 | 29 | 9.0 | 20622.0 | 12294.0 |
| 845 | 제주특별자치도 | 서귀포시 | 여자 | 84364.0 | 4905.0 | 3820.0 | 4427 | 5524.0 | 4449.0 | 4019.0 | 3845 | 3027.0 | 1485.0 | 630.0 | 213 | 68.0 | 18676.0 | 17736.0 |
pivot_table
pop = pd.pivot_table(
data=population,
index=["광역시도", "시도"],
columns=["구분"],
values=["인구수", "20-39세", "65세이상"]
)
pop
| 20-39세 | 65세이상 | 인구수 | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| 구분 | 남자 | 여자 | 합계 | 남자 | 여자 | 합계 | 남자 | 여자 | 합계 | |
| 광역시도 | 시도 | |||||||||
| 강원도 | 강릉시 | 26286.0 | 23098.0 | 49384.0 | 15767.0 | 21912.0 | 37679.0 | 106231.0 | 107615.0 | 213846.0 |
| 고성군 | 4494.0 | 2529.0 | 7023.0 | 2900.0 | 4251.0 | 7151.0 | 15899.0 | 14215.0 | 30114.0 | |
| 동해시 | 11511.0 | 9753.0 | 21264.0 | 6392.0 | 8732.0 | 15124.0 | 47166.0 | 46131.0 | 93297.0 | |
| 삼척시 | 8708.0 | 7115.0 | 15823.0 | 5892.0 | 8718.0 | 14610.0 | 35253.0 | 34346.0 | 69599.0 | |
| 속초시 | 9956.0 | 8752.0 | 18708.0 | 5139.0 | 7613.0 | 12752.0 | 40288.0 | 41505.0 | 81793.0 | |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 충청북도 | 진천군 | 9391.0 | 7622.0 | 17013.0 | 4731.0 | 6575.0 | 11306.0 | 36387.0 | 33563.0 | 69950.0 |
| 청원구 | 32216.0 | 27805.0 | 60021.0 | 8417.0 | 11914.0 | 20331.0 | 97006.0 | 93807.0 | 190813.0 | |
| 청주시 | 128318.0 | 115719.0 | 244037.0 | 37882.0 | 53671.0 | 91553.0 | 419323.0 | 415874.0 | 835197.0 | |
| 충주시 | 26600.0 | 22757.0 | 49357.0 | 14407.0 | 20383.0 | 34790.0 | 104877.0 | 103473.0 | 208350.0 | |
| 흥덕구 | 40933.0 | 37675.0 | 78608.0 | 9788.0 | 13671.0 | 23459.0 | 127647.0 | 125916.0 | 253563.0 | |
소멸 비율 계산
pop["소멸비율"] = pop["20-39세", "여자"] / (pop["65세이상", "합계"] / 2)
pop.tail()
| 20-39세 | 65세이상 | 인구수 | 소멸비율 | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 구분 | 남자 | 여자 | 합계 | 남자 | 여자 | 합계 | 남자 | 여자 | 합계 | ||
| 광역시도 | 시도 | ||||||||||
| 충청북도 | 진천군 | 9391.0 | 7622.0 | 17013.0 | 4731.0 | 6575.0 | 11306.0 | 36387.0 | 33563.0 | 69950.0 | 1.348311 |
| 청원구 | 32216.0 | 27805.0 | 60021.0 | 8417.0 | 11914.0 | 20331.0 | 97006.0 | 93807.0 | 190813.0 | 2.735232 | |
| 청주시 | 128318.0 | 115719.0 | 244037.0 | 37882.0 | 53671.0 | 91553.0 | 419323.0 | 415874.0 | 835197.0 | 2.527913 | |
| 충주시 | 26600.0 | 22757.0 | 49357.0 | 14407.0 | 20383.0 | 34790.0 | 104877.0 | 103473.0 | 208350.0 | 1.308249 | |
| 흥덕구 | 40933.0 | 37675.0 | 78608.0 | 9788.0 | 13671.0 | 23459.0 | 127647.0 | 125916.0 | 253563.0 | 3.211987 | |
소멸 위기 지역 컬럼 생성
pop["소멸위기지역"] = pop["소멸비율"] < 1.0
pop
| 20-39세 | 65세이상 | 인구수 | 소멸비율 | 소멸위기지역 | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 구분 | 남자 | 여자 | 합계 | 남자 | 여자 | 합계 | 남자 | 여자 | 합계 | |||
| 광역시도 | 시도 | |||||||||||
| 강원도 | 강릉시 | 26286.0 | 23098.0 | 49384.0 | 15767.0 | 21912.0 | 37679.0 | 106231.0 | 107615.0 | 213846.0 | 1.226041 | False |
| 고성군 | 4494.0 | 2529.0 | 7023.0 | 2900.0 | 4251.0 | 7151.0 | 15899.0 | 14215.0 | 30114.0 | 0.707314 | True | |
| 동해시 | 11511.0 | 9753.0 | 21264.0 | 6392.0 | 8732.0 | 15124.0 | 47166.0 | 46131.0 | 93297.0 | 1.289738 | False | |
| 삼척시 | 8708.0 | 7115.0 | 15823.0 | 5892.0 | 8718.0 | 14610.0 | 35253.0 | 34346.0 | 69599.0 | 0.973990 | True | |
| 속초시 | 9956.0 | 8752.0 | 18708.0 | 5139.0 | 7613.0 | 12752.0 | 40288.0 | 41505.0 | 81793.0 | 1.372647 | False | |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 충청북도 | 진천군 | 9391.0 | 7622.0 | 17013.0 | 4731.0 | 6575.0 | 11306.0 | 36387.0 | 33563.0 | 69950.0 | 1.348311 | False |
| 청원구 | 32216.0 | 27805.0 | 60021.0 | 8417.0 | 11914.0 | 20331.0 | 97006.0 | 93807.0 | 190813.0 | 2.735232 | False | |
| 청주시 | 128318.0 | 115719.0 | 244037.0 | 37882.0 | 53671.0 | 91553.0 | 419323.0 | 415874.0 | 835197.0 | 2.527913 | False | |
| 충주시 | 26600.0 | 22757.0 | 49357.0 | 14407.0 | 20383.0 | 34790.0 | 104877.0 | 103473.0 | 208350.0 | 1.308249 | False | |
| 흥덕구 | 40933.0 | 37675.0 | 78608.0 | 9788.0 | 13671.0 | 23459.0 | 127647.0 | 125916.0 | 253563.0 | 3.211987 | False | |
소멸 위기 지역 조회
pop[pop["소멸위기지역"] == True].index.get_level_values(1)
=>
Index(['고성군', '삼척시', '양양군', '영월군', '정선군', '평창군', '홍천군', '횡성군', '가평군', '양평군',
'연천군', '거창군', '고성군', '남해군', '밀양시', '산청군', '의령군', '창녕군',
.
.
.
'괴산군', '단양군',
'보은군', '영동군', '옥천군'],
dtype='object', name='시도')
pop.reset_index(inplace=True)
pop.head()
| 광역시도 | 시도 | 20-39세 | 65세이상 | 인구수 | 소멸비율 | 소멸위기지역 | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 구분 | 남자 | 여자 | 합계 | 남자 | 여자 | 합계 | 남자 | 여자 | 합계 | ||||
| 0 | 강원도 | 강릉시 | 26286.0 | 23098.0 | 49384.0 | 15767.0 | 21912.0 | 37679.0 | 106231.0 | 107615.0 | 213846.0 | 1.226041 | False |
| 1 | 강원도 | 고성군 | 4494.0 | 2529.0 | 7023.0 | 2900.0 | 4251.0 | 7151.0 | 15899.0 | 14215.0 | 30114.0 | 0.707314 | True |
| 2 | 강원도 | 동해시 | 11511.0 | 9753.0 | 21264.0 | 6392.0 | 8732.0 | 15124.0 | 47166.0 | 46131.0 | 93297.0 | 1.289738 | False |
| 3 | 강원도 | 삼척시 | 8708.0 | 7115.0 | 15823.0 | 5892.0 | 8718.0 | 14610.0 | 35253.0 | 34346.0 | 69599.0 | 0.973990 | True |
| 4 | 강원도 | 속초시 | 9956.0 | 8752.0 | 18708.0 | 5139.0 | 7613.0 | 12752.0 | 40288.0 | 41505.0 | 81793.0 | 1.372647 | False |
tmp_columns = [
pop.columns.get_level_values(0)[n] + pop.columns.get_level_values(1)[n]
for n in range(0, len(pop.columns.get_level_values(0)))
]
pop.columns = tmp_columns
pop.head()
| 광역시도 | 시도 | 20-39세남자 | 20-39세여자 | 20-39세합계 | 65세이상남자 | 65세이상여자 | 65세이상합계 | 인구수남자 | 인구수여자 | 인구수합계 | 소멸비율 | 소멸위기지역 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 강원도 | 강릉시 | 26286.0 | 23098.0 | 49384.0 | 15767.0 | 21912.0 | 37679.0 | 106231.0 | 107615.0 | 213846.0 | 1.226041 | False |
| 1 | 강원도 | 고성군 | 4494.0 | 2529.0 | 7023.0 | 2900.0 | 4251.0 | 7151.0 | 15899.0 | 14215.0 | 30114.0 | 0.707314 | True |
| 2 | 강원도 | 동해시 | 11511.0 | 9753.0 | 21264.0 | 6392.0 | 8732.0 | 15124.0 | 47166.0 | 46131.0 | 93297.0 | 1.289738 | False |
| 3 | 강원도 | 삼척시 | 8708.0 | 7115.0 | 15823.0 | 5892.0 | 8718.0 | 14610.0 | 35253.0 | 34346.0 | 69599.0 | 0.973990 | True |
| 4 | 강원도 | 속초시 | 9956.0 | 8752.0 | 18708.0 | 5139.0 | 7613.0 | 12752.0 | 40288.0 | 41505.0 | 81793.0 | 1.372647 | False |
3. 지도 시각화를 위한 지역별 ID 만들기
pop.info()
=>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 264 entries, 0 to 263
Data columns (total 13 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 광역시도 264 non-null object
1 시도 264 non-null object
2 20-39세남자 264 non-null float64
3 20-39세여자 264 non-null float64
4 20-39세합계 264 non-null float64
5 65세이상남자 264 non-null float64
6 65세이상여자 264 non-null float64
7 65세이상합계 264 non-null float64
8 인구수남자 264 non-null float64
9 인구수여자 264 non-null float64
10 인구수합계 264 non-null float64
11 소멸비율 264 non-null float64
12 소멸위기지역 264 non-null bool
dtypes: bool(1), float64(10), object(2)
memory usage: 25.1+ KB
pop["시도"].unique()
=>
array(['강릉시', '고성군', '동해시', '삼척시', '속초시', '양구군', '양양군', '영월군', '원주시',
'인제군', '정선군', '철원군', '춘천시', '태백시', '평창군', '홍천군', '화천군', '횡성군',
.
.
.
'단양군',
'보은군', '상당구', '서원구', '영동군', '옥천군', '음성군', '제천시', '증평군', '진천군',
'청원구', '청주시', '충주시', '흥덕구'], dtype=object)
si_name = [None] * len(pop)
tmp_gu_dict = {
"수원": ["장안구", "권선구", "팔달구", "영통구"],
"성남": ["수정구", "중원구", "분당구"],
"안양": ["만안구", "동안구"],
"안산": ["상록구", "단원구"],
"고양": ["덕양구", "일산동구", "일산서구"],
"용인": ["처인구", "기흥구", "수지구"],
"청주": ["상당구", "서원구", "흥덕구", "청원구"],
"천안": ["동남구", "서북구"],
"전주": ["완산구", "덕진구"],
"포항": ["남구", "북구"],
"창원": ["의창구", "성산구", "진해구", "마산합포구", "마산회원구"],
"부천": ["오정구", "원미구", "소사구"]
}
pop["광역시도"].unique()
=>
array(['강원도', '경기도', '경상남도', '경상북도', '광주광역시', '대구광역시', '대전광역시', '부산광역시',
'서울특별시', '세종특별자치시', '울산광역시', '인천광역시', '전라남도', '전라북도', '제주특별자치도',
'충청남도', '충청북도'], dtype=object)
pop["시도"].unique()
=>
array(['강릉시', '고성군', '동해시', '삼척시', '속초시', '양구군', '양양군', '영월군', '원주시',
'인제군', '정선군', '철원군', '춘천시', '태백시', '평창군', '홍천군', '화천군', '횡성군',
.
.
.
'보은군', '상당구', '서원구', '영동군', '옥천군', '음성군', '제천시', '증평군', '진천군',
'청원구', '청주시', '충주시', '흥덕구'], dtype=object)
(1) 일반 시 이름과 세종시, 광역시도 일반 구 정리
for idx, row in pop.iterrows():
if row["광역시도"][-3:] not in ["광역시", "특별시", "자치시"]:
si_name[idx] = row["시도"][:-1]
elif row["광역시도"] == "세종특별자치시":
si_name[idx] = "세종"
else:
if len(row["시도"]) == 2:
si_name[idx] = row["광역시도"][:2] + " " + row["시도"]
else:
si_name[idx] = row["광역시도"][:2] + " " + row["시도"][:-1]
(2) 행정구
for idx, row in pop.iterrows():
if row["광역시도"][-3:] not in ["광역시", "특별시", "자치시"]:
for keys, values in tmp_gu_dict.items(): # dataframe -> iterrows() == dictionary -> items()
if row["시도"] in values:
if len(row["시도"]) == 2:
si_name[idx] = keys + " " + row["시도"]
elif row["시도"] in ["마산합포구", "마산회원구"]:
si_name[idx] = keys + " " + row["시도"][2:-1]
else:
si_name[idx] = keys + " " + row["시도"][:-1]
(3) 고성군
for idx, row in pop.iterrows():
if row["광역시도"][-3:] not in ["광역시", "특별시", "자치시"]:
if row["시도"][:-1] == "고성" and row["광역시도"] == "강원도":
si_name[idx] = "고성(강원)"
elif row["시도"][:-1] == "고성" and row["광역시도"] == "경상남도":
si_name[idx] = "고성(경남)"
pop["ID"] = si_name
pop
| 광역시도 | 시도 | 20-39세남자 | 20-39세여자 | 20-39세합계 | 65세이상남자 | 65세이상여자 | 65세이상합계 | 인구수남자 | 인구수여자 | 인구수합계 | 소멸비율 | 소멸위기지역 | ID | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 강원도 | 강릉시 | 26286.0 | 23098.0 | 49384.0 | 15767.0 | 21912.0 | 37679.0 | 106231.0 | 107615.0 | 213846.0 | 1.226041 | False | 강릉 |
| 1 | 강원도 | 고성군 | 4494.0 | 2529.0 | 7023.0 | 2900.0 | 4251.0 | 7151.0 | 15899.0 | 14215.0 | 30114.0 | 0.707314 | True | 고성(강원) |
| 2 | 강원도 | 동해시 | 11511.0 | 9753.0 | 21264.0 | 6392.0 | 8732.0 | 15124.0 | 47166.0 | 46131.0 | 93297.0 | 1.289738 | False | 동해 |
| 3 | 강원도 | 삼척시 | 8708.0 | 7115.0 | 15823.0 | 5892.0 | 8718.0 | 14610.0 | 35253.0 | 34346.0 | 69599.0 | 0.973990 | True | 삼척 |
| 4 | 강원도 | 속초시 | 9956.0 | 8752.0 | 18708.0 | 5139.0 | 7613.0 | 12752.0 | 40288.0 | 41505.0 | 81793.0 | 1.372647 | False | 속초 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 259 | 충청북도 | 진천군 | 9391.0 | 7622.0 | 17013.0 | 4731.0 | 6575.0 | 11306.0 | 36387.0 | 33563.0 | 69950.0 | 1.348311 | False | 진천 |
| 260 | 충청북도 | 청원구 | 32216.0 | 27805.0 | 60021.0 | 8417.0 | 11914.0 | 20331.0 | 97006.0 | 93807.0 | 190813.0 | 2.735232 | False | 청주 청원 |
| 261 | 충청북도 | 청주시 | 128318.0 | 115719.0 | 244037.0 | 37882.0 | 53671.0 | 91553.0 | 419323.0 | 415874.0 | 835197.0 | 2.527913 | False | 청주 |
| 262 | 충청북도 | 충주시 | 26600.0 | 22757.0 | 49357.0 | 14407.0 | 20383.0 | 34790.0 | 104877.0 | 103473.0 | 208350.0 | 1.308249 | False | 충주 |
| 263 | 충청북도 | 흥덕구 | 40933.0 | 37675.0 | 78608.0 | 9788.0 | 13671.0 | 23459.0 | 127647.0 | 125916.0 | 253563.0 | 3.211987 | False | 청주 흥덕 |
del pop["20-39세남자"]
del pop["65세이상남자"]
del pop["65세이상여자"]
4. 지도 그리기(카르토그램)
draw_korea_raw = pd.read_excel("../data/07_draw_korea_raw.xlsx")
draw_korea_raw
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 철원 | 화천 | 양구 | 고성(강원) | NaN | NaN | NaN |
| 1 | NaN | NaN | NaN | 양주 | 동두천 | 연천 | 포천 | 의정부 | 인제 | 춘천 | 속초 | NaN | NaN | NaN |
| 2 | NaN | NaN | NaN | 고양 덕양 | 고양 일산동 | 서울 도봉 | 서울 노원 | 남양주 | 홍천 | 횡성 | 양양 | NaN | NaN | NaN |
| 3 | NaN | NaN | 파주 | 고양 일산서 | 김포 | 서울 강북 | 서울 성북 | 가평 | 구리 | 하남 | 정선 | 강릉 | NaN | NaN |
| 4 | NaN | NaN | 부천 소사 | 안양 만안 | 광명 | 서울 서대문 | 서울 종로 | 서울 동대문 | 서울 중랑 | 양평 | 태백 | 동해 | NaN | NaN |
| 5 | NaN | 인천 강화 | 부천 원미 | 안양 동안 | 서울 은평 | 서울 마포 | 서울 중구 | 서울 성동 | 서울 강동 | 여주 | 원주 | 삼척 | NaN | NaN |
| 6 | NaN | 인천 서구 | 부천 오정 | 시흥 | 서울 강서 | 서울 동작 | 서울 용산 | 서울 광진 | 서울 송파 | 이천 | 평창 | 울진 | NaN | NaN |
| 7 | NaN | 인천 동구 | 인천 계양 | 안산 상록 | 서울 양천 | 서울 관악 | 서울 서초 | 성남 중원 | 과천 | 광주 | 영월 | 영덕 | NaN | NaN |
| 8 | NaN | NaN | 인천 부평 | 안산 단원 | 서울 영등포 | 서울 금천 | 서울 강남 | 성남 분당 | 성남 수정 | 용인 수지 | 문경 | 봉화 | NaN | 울릉 |
| 9 | NaN | 인천 중구 | 인천 남구 | 화성 | 서울 구로 | 군포 | 의왕 | 수원 영통 | 용인 기흥 | 용인 처인 | 안동 | 영양 | NaN | NaN |
| 10 | 인천 옹진 | 인천 연수 | 인천 남동 | 오산 | 안성 | 수원 권선 | 수원 장안 | 제천 | 예천 | 영주 | 구미 | 청송 | 포항 북구 | NaN |
| 11 | 태안 | 아산 | 천안 동남 | 천안 서북 | 평택 | 음성 | 수원 팔달 | 단양 | 상주 | 김천 | 군위 | 의성 | 포항 남구 | NaN |
| 12 | NaN | 당진 | 홍성 | 예산 | 공주 | 진천 | 충주 | 청주 흥덕 | 괴산 | 칠곡 | 영천 | 경산 | 경주 | NaN |
| 13 | NaN | 서산 | 보령 | 청양 | 세종 | 대전 대덕 | 증평 | 청주 청원 | 보은 | 고령 | 청도 | 성주 | 울산 북구 | NaN |
| 14 | NaN | NaN | 부여 | 논산 | 계룡 | 대전 동구 | 청주 상당 | 청주 서원 | 대구 북구 | 대구 중구 | 대구 수성 | 울산 울주 | 울산 동구 | NaN |
| 15 | NaN | NaN | 서천 | 금산 | 대전 유성 | 대전 중구 | 옥천 | 영동 | 대구 서구 | 대구 남구 | 대구 동구 | 울산 중구 | 울산 남구 | NaN |
| 16 | NaN | NaN | 군산 | 익산 | 대전 서구 | 무주 | 거창 | 합천 | 대구 달서 | 대구 달성 | 부산 금정 | 부산 동래 | 부산 기장 | NaN |
| 17 | NaN | NaN | 부안 | 김제 | 완주 | 장수 | 함양 | 창녕 | 밀양 | 부산 북구 | 부산 부산진 | 부산 연제 | 부산 해운대 | NaN |
| 18 | NaN | 고창 | 정읍 | 전주 덕진 | 진안 | 남원 | 진주 | 의령 | 부산 강서 | 부산 사상 | 부산 동구 | 부산 중구 | NaN | NaN |
| 19 | NaN | 영광 | 장성 | 전주 완산 | 임실 | 산청 | 함안 | 양산 | 창원 합포 | 부산 서구 | 부산 사하 | 부산 남구 | NaN | NaN |
| 20 | NaN | 함평 | 담양 | 순창 | 구례 | 하동 | 창원 의창 | 창원 성산 | 창원 진해 | 김해 | 부산 영도 | 부산 수영 | NaN | NaN |
| 21 | 신안 | 무안 | 광주 광산 | 곡성 | 화순 | 광양 | 사천 | 창원 회원 | 통영 | NaN | NaN | NaN | NaN | NaN |
| 22 | 목포 | 나주 | 광주 서구 | 광주 북구 | 순천 | 고흥 | 남해 | 고성(경남) | 거제 | NaN | NaN | NaN | NaN | NaN |
| 23 | 해남 | 영암 | 광주 남구 | 광주 동구 | 여수 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 24 | 진도 | 강진 | 장흥 | 보성 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 25 | NaN | NaN | 완도 | NaN | NaN | 제주 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 26 | NaN | NaN | NaN | NaN | NaN | 서귀포 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
draw_korea_raw_stacked = pd.DataFrame(draw_korea_raw.stack())
draw_korea_raw_stacked
| 0 | ||
|---|---|---|
| 0 | 7 | 철원 |
| 8 | 화천 | |
| 9 | 양구 | |
| 10 | 고성(강원) | |
| 1 | 3 | 양주 |
| ... | ... | ... |
| 24 | 2 | 장흥 |
| 3 | 보성 | |
| 25 | 2 | 완도 |
| 5 | 제주 | |
| 26 | 5 | 서귀포 |
draw_korea_raw_stacked.reset_index(inplace=True)
draw_korea_raw_stacked
| level_0 | level_1 | 0 | |
|---|---|---|---|
| 0 | 0 | 7 | 철원 |
| 1 | 0 | 8 | 화천 |
| 2 | 0 | 9 | 양구 |
| 3 | 0 | 10 | 고성(강원) |
| 4 | 1 | 3 | 양주 |
| ... | ... | ... | ... |
| 247 | 24 | 2 | 장흥 |
| 248 | 24 | 3 | 보성 |
| 249 | 25 | 2 | 완도 |
| 250 | 25 | 5 | 제주 |
| 251 | 26 | 5 | 서귀포 |
콜럼 재정의
draw_korea_raw_stacked.rename(
columns={
"level_0": "y",
"level_1": "x",
0: "ID"
}, inplace=True
)
draw_korea = draw_korea_raw_stacked
draw_korea
| y | x | ID | |
|---|---|---|---|
| 0 | 0 | 7 | 철원 |
| 1 | 0 | 8 | 화천 |
| 2 | 0 | 9 | 양구 |
| 3 | 0 | 10 | 고성(강원) |
| 4 | 1 | 3 | 양주 |
| ... | ... | ... | ... |
| 247 | 24 | 2 | 장흥 |
| 248 | 24 | 3 | 보성 |
| 249 | 25 | 2 | 완도 |
| 250 | 25 | 5 | 제주 |
| 251 | 26 | 5 | 서귀포 |
우리나라 경계선
BORDER_LINES = [
[(5, 1), (5, 2), (7, 2), (7, 3), (11, 3), (11, 0)], # 인천
[(5, 4), (5, 5), (2, 5), (2, 7), (4, 7), (4, 9), (7, 9), (7, 7), (9, 7), (9, 5), (10, 5), (10, 4), (5, 4)], # 서울
[(1, 7), (1, 8), (3, 8), (3, 10), (10, 10), (10, 7), (12, 7), (12, 6), (11, 6), (11, 5), (12, 5), (12, 4), (11, 4), (11, 3)], # 경기도
[(8, 10), (8, 11), (6, 11), (6, 12)], # 강원도
[(12, 5), (13, 5), (13, 4), (14, 4), (14, 5), (15, 5),(15, 4), (16, 4), (16, 2)], # 충청북도
[(16, 4), (17, 4), (17, 5), (16, 5), (16, 6), (19, 6), (19, 5), (20, 5), (20, 4), (21, 4), (21, 3), (19, 3), (19, 1)], # 전라북도
[(13, 5), (13, 6), (16, 6)],
[(13, 5), (14, 5)], # 대전시, 세종시
[(21 ,2), (21, 3), (22, 3), (22, 4), (24, 4), (24, 2), (21, 2)], # 광주
[(20, 5), (21, 5), (21, 6), (23, 6)], # 전라남도
[(10, 8), (12, 8), (12, 9), (14, 9), (14, 8), (16, 8), (16, 6)], # 충청북도
[(14, 9), (14, 11), (14, 12), (13, 12), (13, 13)], # 경상북도
[(15, 8), (17, 8), (17, 10), (16, 10), (16, 11), (14, 11)], # 대구
[(17, 9), (18, 9), (18, 8), (19, 8), (19, 9), (20, 9), (20, 10), (21, 10)], # 부산
[(16, 11), (16, 13)],
[(27, 5), (27, 6), (25, 6)]
]
def plot_text_simple(draw_korea):
for idx, row in draw_korea.iterrows():
if len(row["ID"].split()) == 2:
dispname = "{}\n{}".format(row["ID"].split()[0], row["ID"].split()[1])
elif row["ID"][:2] == "고성":
dispname = "고성"
else:
dispname = row["ID"]
if len(dispname.splitlines()[-1]) >= 3:
fontsize, linespacing = 9.5, 1.5
else:
fontsize, linespacing = 11, 1.2
plt.annotate(
dispname,
(row["x"] + 0.5, row["y"] + 0.5),
weight="bold",
fontsize=fontsize,
linespacing=linespacing,
ha="center", # 수평 정렬
va="center", # 수직 정렬
)
def simpleDraw(draw_korea):
plt.figure(figsize=(8, 11))
plot_text_simple(draw_korea)
for path in BORDER_LINES:
ys, xs = zip(*path)
plt.plot(xs, ys, c="black", lw=1.5)
plt.gca().invert_yaxis()
plt.axis("off")
plt.tight_layout()
plt.show()
simpleDraw(draw_korea)

검증 작업
set(draw_korea["ID"].unique()) - set(pop["ID"].unique())
=>
set()
set(pop["ID"].unique()) - set(draw_korea["ID"].unique())
=>
{'고양', '부천', '성남', '수원', '안산', '안양', '용인', '전주', '창원', '천안', '청주', '포항'}
tmp_list = list(set(pop["ID"].unique()) - set(draw_korea["ID"].unique()))
for tmp in tmp_list:
pop = pop.drop(pop[pop["ID"] == tmp].index)
print(set(pop["ID"].unique()) - set(draw_korea["ID"].unique()))
=>
set()
merge()
pop = pd.merge(pop, draw_korea, how="left", on="ID")
pop.head()
| 광역시도 | 시도 | 20-39세여자 | 20-39세합계 | 65세이상합계 | 인구수남자 | 인구수여자 | 인구수합계 | 소멸비율 | 소멸위기지역 | ID | y | x | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 강원도 | 강릉시 | 23098.0 | 49384.0 | 37679.0 | 106231.0 | 107615.0 | 213846.0 | 1.226041 | 0 | 강릉 | 3 | 11 |
| 1 | 강원도 | 고성군 | 2529.0 | 7023.0 | 7151.0 | 15899.0 | 14215.0 | 30114.0 | 0.707314 | 1 | 고성(강원) | 0 | 10 |
| 2 | 강원도 | 동해시 | 9753.0 | 21264.0 | 15124.0 | 47166.0 | 46131.0 | 93297.0 | 1.289738 | 0 | 동해 | 4 | 11 |
| 3 | 강원도 | 삼척시 | 7115.0 | 15823.0 | 14610.0 | 35253.0 | 34346.0 | 69599.0 | 0.973990 | 1 | 삼척 | 5 | 11 |
| 4 | 강원도 | 속초시 | 8752.0 | 18708.0 | 12752.0 | 40288.0 | 41505.0 | 81793.0 | 1.372647 | 0 | 속초 | 1 | 10 |
그림 그리기 위한 데이터를 계산하는 함수
- 색상을 만들 때, 최소값을 흰색
- blockedMap: 인구현황(pop)
- targetData: 그리고싶은 컬럼
def get_data_info(targetData, blockedMap):
whitelabelmin = (
max(blockedMap[targetData]) - min(blockedMap[targetData])
) * 0.25 + min(blockedMap[targetData])
vmin = min(blockedMap[targetData])
vmax = max(blockedMap[targetData])
mapdata = blockedMap.pivot_table(index="y", columns="x", values=targetData)
return mapdata, vmax, vmin, whitelabelmin
def get_data_info_for_zero_center(targetData, blockedMap):
whitelabelmin = 5
tmp_max = max(
[np.abs(min(blockedMap[targetData])), np.abs(max(blockedMap[targetData]))]
)
vmin, vmax = -tmp_max, tmp_max
mapdata = blockedMap.pivot_table(index="y", columns="x", values=targetData)
return mapdata, vmax, vmin, whitelabelmin
def plot_text(targetData, blockedMap, whitelabelmin):
for idx, row in blockedMap.iterrows():
if len(row["ID"].split()) == 2:
dispname = "{}\n{}".format(row["ID"].split()[0], row["ID"].split()[1])
elif row["ID"][:2] == "고성":
dispname = "고성"
else:
dispname = row["ID"]
if len(dispname.splitlines()[-1]) >= 3:
fontsize, linespacing = 9.5, 1.5
else:
fontsize, linespacing = 11, 1.2
annocolor = "white" if np.abs(row[targetData]) > whitelabelmin else "black"
plt.annotate(
dispname,
(row["x"] + 0.5, row["y"] + 0.5),
weight="bold",
color=annocolor,
fontsize=fontsize,
linespacing=linespacing,
ha="center", # 수평 정렬
va="center", # 수직 정렬
)
def drawKorea(targetData, blockedMap, cmapname, zeroCenter=False):
if zeroCenter:
masked_mapdata, vmax, vmin, whitelabelmin = get_data_info_for_zero_center(targetData, blockedMap)
if not zeroCenter:
masked_mapdata, vmax, vmin, whitelabelmin = get_data_info(targetData, blockedMap)
plt.figure(figsize=(8, 11))
plt.pcolor(masked_mapdata, vmin=vmin, vmax=vmax, cmap=cmapname, edgecolor="#aaaaaa", linewidth=0.5)
plot_text(targetData, blockedMap, whitelabelmin)
for path in BORDER_LINES:
ys, xs = zip(*path)
plt.plot(xs, ys, c="black", lw=1.5)
plt.gca().invert_yaxis()
plt.axis("off")
plt.tight_layout()
cb = plt.colorbar(shrink=0.1, aspect=10)
cb.set_label(targetData)
plt.show()
drawKorea("인구수합계", pop, "Blues")

pop["소멸위기지역"]
=>
0 0
1 1
2 0
3 1
4 0
..
247 0
248 0
249 0
250 0
251 0
Name: 소멸위기지역, Length: 252, dtype: int64
소멸 위기 지역
pop["소멸위기지역"] = [1 if con else 0 for con in pop["소멸위기지역"]]
drawKorea("소멸위기지역", pop, "Reds")

여성비
pop["여성비"] = (pop["인구수여자"] / pop["인구수합계"] - 0.5) * 100
drawKorea("여성비", pop, "RdBu", zeroCenter=True)

2030여성비
pop["2030여성비"] = (pop["20-39세여자"] / pop["20-39세합계"] - 0.5) * 100
drawKorea("2030여성비", pop, "RdBu", zeroCenter=True)

5. folium
import folium
import json
pop_folium = pop.set_index("ID")
pop_folium
| 광역시도 | 시도 | 20-39세여자 | 20-39세합계 | 65세이상합계 | 인구수남자 | 인구수여자 | 인구수합계 | 소멸비율 | 소멸위기지역 | y | x | 여성비 | 2030여성비 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | ||||||||||||||
| 강릉 | 강원도 | 강릉시 | 23098.0 | 49384.0 | 37679.0 | 106231.0 | 107615.0 | 213846.0 | 1.226041 | 0 | 3 | 11 | 0.323597 | -3.227766 |
| 고성(강원) | 강원도 | 고성군 | 2529.0 | 7023.0 | 7151.0 | 15899.0 | 14215.0 | 30114.0 | 0.707314 | 1 | 0 | 10 | -2.796042 | -13.989748 |
| 동해 | 강원도 | 동해시 | 9753.0 | 21264.0 | 15124.0 | 47166.0 | 46131.0 | 93297.0 | 1.289738 | 0 | 4 | 11 | -0.554680 | -4.133747 |
| 삼척 | 강원도 | 삼척시 | 7115.0 | 15823.0 | 14610.0 | 35253.0 | 34346.0 | 69599.0 | 0.973990 | 1 | 5 | 11 | -0.651590 | -5.033812 |
| 속초 | 강원도 | 속초시 | 8752.0 | 18708.0 | 12752.0 | 40288.0 | 41505.0 | 81793.0 | 1.372647 | 0 | 1 | 10 | 0.743951 | -3.217875 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 증평 | 충청북도 | 증평군 | 4554.0 | 10085.0 | 5323.0 | 19110.0 | 18198.0 | 37308.0 | 1.711065 | 0 | 13 | 6 | -1.222258 | -4.843827 |
| 진천 | 충청북도 | 진천군 | 7622.0 | 17013.0 | 11306.0 | 36387.0 | 33563.0 | 69950.0 | 1.348311 | 0 | 12 | 5 | -2.018585 | -5.198965 |
| 청주 청원 | 충청북도 | 청원구 | 27805.0 | 60021.0 | 20331.0 | 97006.0 | 93807.0 | 190813.0 | 2.735232 | 0 | 13 | 7 | -0.838255 | -3.674547 |
| 충주 | 충청북도 | 충주시 | 22757.0 | 49357.0 | 34790.0 | 104877.0 | 103473.0 | 208350.0 | 1.308249 | 0 | 12 | 6 | -0.336933 | -3.893065 |
| 청주 흥덕 | 충청북도 | 흥덕구 | 37675.0 | 78608.0 | 23459.0 | 127647.0 | 125916.0 | 253563.0 | 3.211987 | 0 | 12 | 7 | -0.341335 | -2.072308 |
인구수합계 지도시각화
geo_path = "../data/07_skorea_municipalities_geo_simple.json"
geo_str = json.load(open(geo_path, encoding="utf-8"))
mymap = folium.Map(location=[36.2002, 127.054], zoom_start=7)
mymap.choropleth(
geo_data=geo_str,
data=pop_folium["인구수합계"],
key_on="feature.id",
columns=[pop_folium.index, pop_folium["인구수합계"]],
fill_color="YlGnBu"
)
mymap

소멸 위기 지역 지도시각화
mymap = folium.Map(location=[36.2002, 127.054], zoom_start=7)
mymap.choropleth(
geo_data=geo_str,
data=pop_folium["소멸위기지역"],
key_on="feature.id",
columns=[pop_folium.index, pop_folium["소멸위기지역"]],
fill_color="PuRd"
)
mymap
