17 분 소요

import warnings
warnings.filterwarnings('ignore')
from IPython.display import Image
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'NanumGothicCoding'
plt.rcParams['font.size'] = 15
import matplotlib as mpl
mpl.rcParams['axes.unicode_minus'] = False
import seaborn as sns
from plotnine import *
import missingno as msno

전국 도시 공원 표준 데이터 => https://www.data.go.kr/dataset/15012890/standard.do

park = pd.read_csv('./data/전국도시공원표준데이터.csv', encoding='euc-kr')
park.shape
(18137, 20)
park.head()
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 공원보유시설(운동시설) 공원보유시설(유희시설) 공원보유시설(편익시설) 공원보유시설(교양시설) 공원보유시설(기타시설) 지정고시일 관리기관명 전화번호 데이터기준일자 제공기관코드 제공기관명 Unnamed: 19
0 26440-00001 구랑공원 문화공원 NaN 부산광역시 강서구 구랑동 1199-7 35.157215 128.854935 9137.0 4 NaN 화장실 NaN 팔각정자, 파고라2, 평의자6, 앉음벽14.38m, 축구장(골대2), 컨테이너, 안... 2011-09-02 부산광역시 강서구청 녹지공원과 051-970-4536 2019-05-02 3360000 부산광역시 강서구 NaN
1 26440-00002 압곡공원 근린공원 NaN 부산광역시 강서구 구랑동 1219 35.154655 128.854727 33756.0 4 NaN NaN NaN 배드민턴장, 족구장, 파고라4, 안내판, 볼라드7, 데크435.11㎡, 데크계단19... 2008-02-28 부산광역시 강서구청 녹지공원과 051-970-4536 2019-05-02 3360000 부산광역시 강서구 NaN
2 26440-00003 서연정공원 소공원 NaN 부산광역시 강서구 대저1동 1330-7 35.216183 128.969558 646.0 7 NaN NaN NaN 앉음벽13.57m, 트렐리스3, 안내판2, 플랜트2, 파고라, 평의자4 2013-01-23 부산광역시 강서구청 녹지공원과 051-970-4536 2019-05-02 3360000 부산광역시 강서구 NaN
3 26440-00004 용두공원 어린이공원 NaN 부산광역시 강서구 대저2동 1870-67 35.183679 128.956007 1620.0 NaN 조합놀이기구, 그네 NaN NaN 정자, 농구장, 평의자6 1998-07-25 부산광역시 강서구청 녹지공원과 051-970-4536 2019-05-02 3360000 부산광역시 강서구 NaN
4 26440-00005 새동내공원 어린이공원 NaN 부산광역시 강서구 대저2동 2407-1 35.174568 128.950612 1009.0 8 조합놀이기구, 그네, 흔들놀이기구2 NaN NaN 정자, 평의자14, 트렐리스2, 안내판, 볼라드 1995-04-07 부산광역시 강서구청 녹지공원과 051-970-4536 2019-05-02 3360000 부산광역시 강서구 NaN
park.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 18137 entries, 0 to 18136
Data columns (total 20 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   관리번호          18137 non-null  object 
 1   공원명           18137 non-null  object 
 2   공원구분          18137 non-null  object 
 3   소재지도로명주소      8039 non-null   object 
 4   소재지지번주소       17158 non-null  object 
 5   위도            18137 non-null  float64
 6   경도            18137 non-null  float64
 7   공원면적          18137 non-null  float64
 8   공원보유시설(운동시설)  4845 non-null   object 
 9   공원보유시설(유희시설)  6964 non-null   object 
 10  공원보유시설(편익시설)  5084 non-null   object 
 11  공원보유시설(교양시설)  1160 non-null   object 
 12  공원보유시설(기타시설)  3116 non-null   object 
 13  지정고시일         15225 non-null  object 
 14  관리기관명         17383 non-null  object 
 15  전화번호          16957 non-null  object 
 16  데이터기준일자       18137 non-null  object 
 17  제공기관코드        18137 non-null  object 
 18  제공기관명         18137 non-null  object 
 19  Unnamed: 19   0 non-null      float64
dtypes: float64(4), object(16)
memory usage: 2.8+ MB
park.isnull().sum()
관리번호                0
공원명                 0
공원구분                0
소재지도로명주소        10098
소재지지번주소           979
위도                  0
경도                  0
공원면적                0
공원보유시설(운동시설)    13292
공원보유시설(유희시설)    11173
공원보유시설(편익시설)    13053
공원보유시설(교양시설)    16977
공원보유시설(기타시설)    15021
지정고시일            2912
관리기관명             754
전화번호             1180
데이터기준일자             0
제공기관코드              0
제공기관명               0
Unnamed: 19     18137
dtype: int64
msno.matrix(park, figsize=[20, 8])
<AxesSubplot:>

output_6_1

Index(['관리번호', '공원명', '공원구분', '소재지도로명주소', '소재지지번주소', '위도', '경도', '공원면적',
       '공원보유시설(운동시설)', '공원보유시설(유희시설)', '공원보유시설(편익시설)', '공원보유시설(교양시설)',
       '공원보유시설(기타시설)', '지정고시일', '관리기관명', '전화번호', '데이터기준일자', '제공기관코드', '제공기관명',
       'Unnamed: 19'],
      dtype='object')
# drop() 함수로 불필요한 컬럼을 제거한다.
# columns 속성에 제거할 열 이름을 적는다. 단, 제거할 열이 2개 이상일 경으 []로 묶는다.
# inplace=True 속성을 지정하면 실행 결과가 데이터프레임에 바로 적용된다.
park.drop(columns=['공원보유시설(운동시설)', '공원보유시설(유희시설)', '공원보유시설(편익시설)', '공원보유시설(교양시설)',
                  '공원보유시설(기타시설)', '지정고시일', '관리기관명', 'Unnamed: 19'], inplace=True)
park
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명
0 26440-00001 구랑공원 문화공원 NaN 부산광역시 강서구 구랑동 1199-7 35.157215 128.854935 9137.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구
1 26440-00002 압곡공원 근린공원 NaN 부산광역시 강서구 구랑동 1219 35.154655 128.854727 33756.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구
2 26440-00003 서연정공원 소공원 NaN 부산광역시 강서구 대저1동 1330-7 35.216183 128.969558 646.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구
3 26440-00004 용두공원 어린이공원 NaN 부산광역시 강서구 대저2동 1870-67 35.183679 128.956007 1620.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구
4 26440-00005 새동내공원 어린이공원 NaN 부산광역시 강서구 대저2동 2407-1 35.174568 128.950612 1009.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구
... ... ... ... ... ... ... ... ... ... ... ... ...
18132 28140-00009 송림4공원 어린이공원 NaN 인천광역시 동구 송림동 291-6 37.478715 126.653257 412.9 032-770-6205 2019-07-30 3500000 인천광역시 동구
18133 47760-00002 서부공원 근린공원 NaN 경상북도 영양군 영양읍 서부리 123 36.660456 129.114953 56045.0 054-680-6340 2019-09-05 5170000 경상북도 영양군
18134 47760-00003 입암공원 근린공원 NaN 경상북도 영양군 입암면 신구리 산27-5 36.594802 129.093007 109262.0 054-680-6340 2019-09-05 5170000 경상북도 영양군
18135 47760-00004 수비공원 근린공원 NaN 경상북도 영양군 수비면 발리리 산48 36.761440 129.200011 67159.0 054-680-6340 2019-09-05 5170000 경상북도 영양군
18136 47760-00005 삼지연꽃 테마파크 수변공원 NaN 경상북도 영양군 영양읍 삼지리 200 36.662816 129.129372 380000.0 054-680-6340 2019-09-05 5170000 경상북도 영양군

18137 rows × 12 columns

msno.matrix(park, figsize=[14, 8])
<AxesSubplot:>

output_9_1

전국 공원 분포 시각화

ggplot(park, aes(x='경도', y='위도')) \
    + geom_point(size=0.5) \
    + theme(text=element_text(family='NanumGothicCoding'), figure_size=[7, 10])

output_11_0

<ggplot: (-9223371847520436883)>
park.plot.scatter(x='경도', y='위도', grid=True, figsize=[7, 10], s=5)
<AxesSubplot:xlabel='경도', ylabel='위도'>

output_12_1

데이터 전처리

park.dtypes
관리번호         object
공원명          object
공원구분         object
소재지도로명주소     object
소재지지번주소      object
위도          float64
경도          float64
공원면적        float64
전화번호         object
데이터기준일자      object
제공기관코드       object
제공기관명        object
dtype: object
park['공원면적'].head()
0     9137.0
1    33756.0
2      646.0
3     1620.0
4     1009.0
Name: 공원면적, dtype: float64
# park['공원면적'] 열의 데이터가 처음부터 차례대로 lambda 뒤의 변수 x에 저장되면서 ':'뒤의 수식을 실행한다.
park['공원면적비율'] = park['공원면적'].apply(lambda x: np.sqrt(x) * 0.01)
park.head()
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율
0 26440-00001 구랑공원 문화공원 NaN 부산광역시 강서구 구랑동 1199-7 35.157215 128.854935 9137.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.955877
1 26440-00002 압곡공원 근린공원 NaN 부산광역시 강서구 구랑동 1219 35.154655 128.854727 33756.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.837281
2 26440-00003 서연정공원 소공원 NaN 부산광역시 강서구 대저1동 1330-7 35.216183 128.969558 646.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.254165
3 26440-00004 용두공원 어린이공원 NaN 부산광역시 강서구 대저2동 1870-67 35.183679 128.956007 1620.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.402492
4 26440-00005 새동내공원 어린이공원 NaN 부산광역시 강서구 대저2동 2407-1 35.174568 128.950612 1009.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.317648
# 도로명주소가 NaN인 데이터의 개수 => 지번주소만 입력된 데이터의 개수
# 도로명주소만 입력되고 지번주소가 입력되지 않은 데이터는 도로명주소 제도가 시행되고 난 후 조성된 공원이다.
park['소재지도로명주소'].isnull().sum()
10098
# 도로명주소는 입력되지 않고 지번주소만 입력된 데이터
# 판다스는 논리 연산자로 &(and)와 |(or)를 사용하고 논리 연산자 양쪽의 조건을 ()로 묶어준다.
park[(park['소재지도로명주소'].isnull()) & (park['소재지지번주소'].notnull())]
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율
0 26440-00001 구랑공원 문화공원 NaN 부산광역시 강서구 구랑동 1199-7 35.157215 128.854935 9137.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.955877
1 26440-00002 압곡공원 근린공원 NaN 부산광역시 강서구 구랑동 1219 35.154655 128.854727 33756.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.837281
2 26440-00003 서연정공원 소공원 NaN 부산광역시 강서구 대저1동 1330-7 35.216183 128.969558 646.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.254165
3 26440-00004 용두공원 어린이공원 NaN 부산광역시 강서구 대저2동 1870-67 35.183679 128.956007 1620.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.402492
4 26440-00005 새동내공원 어린이공원 NaN 부산광역시 강서구 대저2동 2407-1 35.174568 128.950612 1009.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.317648
... ... ... ... ... ... ... ... ... ... ... ... ... ...
18132 28140-00009 송림4공원 어린이공원 NaN 인천광역시 동구 송림동 291-6 37.478715 126.653257 412.9 032-770-6205 2019-07-30 3500000 인천광역시 동구 0.203199
18133 47760-00002 서부공원 근린공원 NaN 경상북도 영양군 영양읍 서부리 123 36.660456 129.114953 56045.0 054-680-6340 2019-09-05 5170000 경상북도 영양군 2.367383
18134 47760-00003 입암공원 근린공원 NaN 경상북도 영양군 입암면 신구리 산27-5 36.594802 129.093007 109262.0 054-680-6340 2019-09-05 5170000 경상북도 영양군 3.305480
18135 47760-00004 수비공원 근린공원 NaN 경상북도 영양군 수비면 발리리 산48 36.761440 129.200011 67159.0 054-680-6340 2019-09-05 5170000 경상북도 영양군 2.591505
18136 47760-00005 삼지연꽃 테마파크 수변공원 NaN 경상북도 영양군 영양읍 삼지리 200 36.662816 129.129372 380000.0 054-680-6340 2019-09-05 5170000 경상북도 영양군 6.164414

10098 rows × 13 columns

# 지번주소가 NaN인 데이터의 개수 => 도로명주소만 입력된 데이터의 개수
park['소재지지번주소'].isnull().sum()
979
# 도로명주소는 입력되고 지번주소가 입력되지 않은 데이터
park[(park['소재지도로명주소'].notnull()) & (park['소재지지번주소'].isnull())]
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율
2132 46130-00071 오복공원 근린공원 전라남도 여수시 경호동 239번지 NaN 34.709529 127.722047 16036.0 061-659-4627 2019-06-13 6460000 전라남도 1.266333
2133 46130-00072 대경도공원 근린공원 전라남도 여수시 경호동 193-2 NaN 34.707635 127.722798 26384.0 061-659-4627 2019-06-13 6460000 전라남도 1.624315
2135 46130-00076 성산공원 근린공원 전라남도 여수시 화장동 949 NaN 34.774538 127.645884 70845.0 061-659-4627 2019-06-13 6460000 전라남도 2.661672
2137 46130-00078 주공공원 어린이공원 전라남도 여수시 신기동 4 NaN 34.765323 127.676103 1500.0 061-659-4627 2019-06-13 6460000 전라남도 0.387298
2138 46130-00079 들몰공원 어린이공원 전라남도 여수시 신기동 5 NaN 34.765144 127.679023 1500.0 061-659-4627 2019-06-13 6460000 전라남도 0.387298
... ... ... ... ... ... ... ... ... ... ... ... ... ...
18115 44800-00078 남당취락2소공원 소공원 충청남도 홍성군 서부면 남당리 859 일원 NaN 36.539355 126.471621 2395.0 041-630-1268 2019-06-25 4600000 충청남도 홍성군 0.489387
18116 44800-00079 옥암1호소공원 소공원 충청남도 홍성군 홍성읍 옥암리 148-8 일원 NaN 36.593251 126.651456 1142.0 041-630-1268 2019-06-25 4600000 충청남도 홍성군 0.337935
18117 44800-00080 옥암2호어린이공원 어린이공원 충청남도 홍성군 홍성읍 오관리 190 일원 NaN 36.599064 126.663734 1612.0 041-630-1268 2019-06-25 4600000 충청남도 홍성군 0.401497
18118 44800-00081 옥암1호어린이공원 어린이공원 충청남도 홍성군 홍성읍 옥암리 381-3 일원 NaN 36.587390 126.646558 1586.0 041-630-1268 2019-06-25 4600000 충청남도 홍성군 0.398246
18119 44800-00082 홍성읍24호소공원 소공원 충청남도 홍성군 홍성읍 오관리 472 일원 NaN 36.599064 126.663734 701.0 041-630-1268 2019-06-25 4600000 충청남도 홍성군 0.264764

979 rows × 13 columns

# 도로명주소와 지번주소가 모두 입력된 데이터
park[(park['소재지도로명주소'].notnull()) & (park['소재지지번주소'].notnull())]
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율
22 26440-00023 명지공원 근린공원 부산광역시 강서구 명지오션시티7로 30 (명지동) 부산광역시 강서구 명지동 3247번지 35.087766 128.908524 170405.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 4.128014
23 26440-00024 철새탐방공원 문화공원 부산광역시 강서구 명지오션시티1로 284 (명지동) 부산광역시 강서구 명지동 3308-3 35.084080 128.911810 1344.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.366606
32 26440-00033 보람공원 근린공원 부산광역시 강서구 녹산산단262로14번길 20 (송정동) 부산광역시 강서구 송정동 1718 35.088095 128.843216 27739.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.665503
38 26440-00039 지사공원(2호근린공원) 근린공원 부산광역시 강서구 과학산단2로20번길 7-7 (지사동) 부산광역시 강서구 지사동 1180 35.151337 128.831400 11232.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.059811
44 26440-00045 화암공원 근린공원 부산광역시 강서구 화전산단5로 131 (화전동) 부산광역시 강서구 화전동 554-3 35.110563 128.877536 21908.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.480135
... ... ... ... ... ... ... ... ... ... ... ... ... ...
18027 11590-00040 국화원 소공원 서울특별시 동작구 상도로30길 39(상도동, 상도두산위브아파트) 서울특별시 동작구 상도동 529 상도두산위브아파트 37.504836 126.943714 757.0 NaN 2019-02-20 3190000 서울특별시 동작구 0.275136
18121 28140-00011 창영공원 어린이공원 인천광역시 동구 우각로 26 인천광역시 동구 창영동 21-15 37.470778 126.639105 1019.8 032-770-6205 2019-07-30 3500000 인천광역시 동구 0.319343
18125 28140-00002 화도진공원 근린공원 인천광역시 동구 화도진로 114 인천광역시 동구 화수동 140-1 37.481481 126.628353 20830.0 032-770-6202 2019-07-30 3500000 인천광역시 동구 1.443260
18126 28140-00003 인천교공원(A,B블럭) 근린공원 인천광역시 동구 방축로 231 인천광역시 동구 송림동 318 37.477844 126.669618 94068.0 032-770-6203 2019-07-30 3500000 인천광역시 동구 3.067051
18128 28140-00005 송현공원 근린공원 인천광역시 동구 솔빛로 51 인천광역시 동구 송현동 163 37.477773 126.639225 72492.0 032-770-6204 2019-07-30 3500000 인천광역시 동구 2.692434

7060 rows × 13 columns

# 도로명주소와 지번주소가 모두 입력되지 않은 데이터
park[(park['소재지도로명주소'].isnull()) & (park['소재지지번주소'].isnull())]
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율
# 도로명주소가 NaN인 데이터를 지번주소로 채운다.
park['소재지도로명주소'].fillna(park['소재지지번주소'], inplace=True)
park
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율
0 26440-00001 구랑공원 문화공원 부산광역시 강서구 구랑동 1199-7 부산광역시 강서구 구랑동 1199-7 35.157215 128.854935 9137.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.955877
1 26440-00002 압곡공원 근린공원 부산광역시 강서구 구랑동 1219 부산광역시 강서구 구랑동 1219 35.154655 128.854727 33756.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.837281
2 26440-00003 서연정공원 소공원 부산광역시 강서구 대저1동 1330-7 부산광역시 강서구 대저1동 1330-7 35.216183 128.969558 646.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.254165
3 26440-00004 용두공원 어린이공원 부산광역시 강서구 대저2동 1870-67 부산광역시 강서구 대저2동 1870-67 35.183679 128.956007 1620.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.402492
4 26440-00005 새동내공원 어린이공원 부산광역시 강서구 대저2동 2407-1 부산광역시 강서구 대저2동 2407-1 35.174568 128.950612 1009.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.317648
... ... ... ... ... ... ... ... ... ... ... ... ... ...
18132 28140-00009 송림4공원 어린이공원 인천광역시 동구 송림동 291-6 인천광역시 동구 송림동 291-6 37.478715 126.653257 412.9 032-770-6205 2019-07-30 3500000 인천광역시 동구 0.203199
18133 47760-00002 서부공원 근린공원 경상북도 영양군 영양읍 서부리 123 경상북도 영양군 영양읍 서부리 123 36.660456 129.114953 56045.0 054-680-6340 2019-09-05 5170000 경상북도 영양군 2.367383
18134 47760-00003 입암공원 근린공원 경상북도 영양군 입암면 신구리 산27-5 경상북도 영양군 입암면 신구리 산27-5 36.594802 129.093007 109262.0 054-680-6340 2019-09-05 5170000 경상북도 영양군 3.305480
18135 47760-00004 수비공원 근린공원 경상북도 영양군 수비면 발리리 산48 경상북도 영양군 수비면 발리리 산48 36.761440 129.200011 67159.0 054-680-6340 2019-09-05 5170000 경상북도 영양군 2.591505
18136 47760-00005 삼지연꽃 테마파크 수변공원 경상북도 영양군 영양읍 삼지리 200 경상북도 영양군 영양읍 삼지리 200 36.662816 129.129372 380000.0 054-680-6340 2019-09-05 5170000 경상북도 영양군 6.164414

18137 rows × 13 columns

park['소재지도로명주소'].isnull().sum()
0
# split() 함수 실행시 expand=True 옵션을 지정하면 데이터프레임으로 분리되서 인덱싱과 슬라이싱을 할 수 있다.
park['소재지도로명주소'].str.split(' ', expand=True)
0 1 2 3 4 5 6 7 8
0 부산광역시 강서구 구랑동 1199-7 None None None None None
1 부산광역시 강서구 구랑동 1219 None None None None None
2 부산광역시 강서구 대저1동 1330-7 None None None None None
3 부산광역시 강서구 대저2동 1870-67 None None None None None
4 부산광역시 강서구 대저2동 2407-1 None None None None None
... ... ... ... ... ... ... ... ... ...
18132 인천광역시 동구 송림동 291-6 None None None None None
18133 경상북도 영양군 영양읍 서부리 123 None None None None
18134 경상북도 영양군 입암면 신구리 산27-5 None None None None
18135 경상북도 영양군 수비면 발리리 산48 None None None None
18136 경상북도 영양군 영양읍 삼지리 200 None None None None

18137 rows × 9 columns

# 도로명주소에서 '시도'만 추출해서 '시도'라는 열을 만들어 park 데이터프레임에 추가한다.
park['시도'] = park['소재지도로명주소'].str.split(' ', expand=True)[0]
park.head()
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율 시도
0 26440-00001 구랑공원 문화공원 부산광역시 강서구 구랑동 1199-7 부산광역시 강서구 구랑동 1199-7 35.157215 128.854935 9137.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.955877 부산광역시
1 26440-00002 압곡공원 근린공원 부산광역시 강서구 구랑동 1219 부산광역시 강서구 구랑동 1219 35.154655 128.854727 33756.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.837281 부산광역시
2 26440-00003 서연정공원 소공원 부산광역시 강서구 대저1동 1330-7 부산광역시 강서구 대저1동 1330-7 35.216183 128.969558 646.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.254165 부산광역시
3 26440-00004 용두공원 어린이공원 부산광역시 강서구 대저2동 1870-67 부산광역시 강서구 대저2동 1870-67 35.183679 128.956007 1620.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.402492 부산광역시
4 26440-00005 새동내공원 어린이공원 부산광역시 강서구 대저2동 2407-1 부산광역시 강서구 대저2동 2407-1 35.174568 128.950612 1009.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.317648 부산광역시
# 도로명주소에서 '구군'만 추출해서 '구군'이라는 열을 만들어 park 데이터프레임에 추가한다.
park['구군'] = park['소재지도로명주소'].str.split(' ', expand=True)[1]
park.head()
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율 시도 구군
0 26440-00001 구랑공원 문화공원 부산광역시 강서구 구랑동 1199-7 부산광역시 강서구 구랑동 1199-7 35.157215 128.854935 9137.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.955877 부산광역시 강서구
1 26440-00002 압곡공원 근린공원 부산광역시 강서구 구랑동 1219 부산광역시 강서구 구랑동 1219 35.154655 128.854727 33756.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.837281 부산광역시 강서구
2 26440-00003 서연정공원 소공원 부산광역시 강서구 대저1동 1330-7 부산광역시 강서구 대저1동 1330-7 35.216183 128.969558 646.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.254165 부산광역시 강서구
3 26440-00004 용두공원 어린이공원 부산광역시 강서구 대저2동 1870-67 부산광역시 강서구 대저2동 1870-67 35.183679 128.956007 1620.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.402492 부산광역시 강서구
4 26440-00005 새동내공원 어린이공원 부산광역시 강서구 대저2동 2407-1 부산광역시 강서구 대저2동 2407-1 35.174568 128.950612 1009.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.317648 부산광역시 강서구
# 도로명주소에서 '읍면동'만 추출해서 '읍면동'이라는 열을 만들어 park 데이터프레임에 추가한다.
park['읍면동'] = park['소재지도로명주소'].str.split(' ', expand=True)[2]
park.head()
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율 시도 구군 읍면동
0 26440-00001 구랑공원 문화공원 부산광역시 강서구 구랑동 1199-7 부산광역시 강서구 구랑동 1199-7 35.157215 128.854935 9137.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.955877 부산광역시 강서구 구랑동
1 26440-00002 압곡공원 근린공원 부산광역시 강서구 구랑동 1219 부산광역시 강서구 구랑동 1219 35.154655 128.854727 33756.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.837281 부산광역시 강서구 구랑동
2 26440-00003 서연정공원 소공원 부산광역시 강서구 대저1동 1330-7 부산광역시 강서구 대저1동 1330-7 35.216183 128.969558 646.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.254165 부산광역시 강서구 대저1동
3 26440-00004 용두공원 어린이공원 부산광역시 강서구 대저2동 1870-67 부산광역시 강서구 대저2동 1870-67 35.183679 128.956007 1620.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.402492 부산광역시 강서구 대저2동
4 26440-00005 새동내공원 어린이공원 부산광역시 강서구 대저2동 2407-1 부산광역시 강서구 대저2동 2407-1 35.174568 128.950612 1009.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.317648 부산광역시 강서구 대저2동
park[['위도', '경도']].describe()
위도 경도
count 18137.000000 18137.000000
mean 36.335922 127.543937
std 1.051835 0.892670
min 27.551606 125.430955
25% 35.275430 126.872301
50% 36.364729 127.130926
75% 37.404278 128.466193
max 38.224926 137.202661
# 위도와 경도가 잘못 입력된 데이터를 추출한다.
park_error = park[(park['위도'] < 32) | (park['경도'] > 132)]
park_error
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율 시도 구군 읍면동
374 11440-00004 와우공원 근린공원 서울특별시 마포구 창전동3-231 등 59필지 서울특별시 마포구 창전동3-231 등 59필지 27.551606 126.929047 73590.0 02-3153-9553 2019-07-22 3130000 서울특별시 마포구 2.712748 서울특별시 마포구 창전동3-231
12926 43113-00080 근린공원5(만수공원) 근린공원 충청북도 청주시 흥덕구 오송읍 만수리 512 충청북도 청주시 흥덕구 오송읍 만수리 512 36.374204 137.202661 33258.0 043-201-4433 2019-06-21 5710000 충청북도 청주시 1.823678 충청북도 청주시 흥덕구
# 올바른 데이터
park_ok = park[(park['위도'] >= 32) & (park['경도'] <= 132)]
park_ok.shape
(18135, 16)
park_ok.head()
관리번호 공원명 공원구분 소재지도로명주소 소재지지번주소 위도 경도 공원면적 전화번호 데이터기준일자 제공기관코드 제공기관명 공원면적비율 시도 구군 읍면동
0 26440-00001 구랑공원 문화공원 부산광역시 강서구 구랑동 1199-7 부산광역시 강서구 구랑동 1199-7 35.157215 128.854935 9137.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.955877 부산광역시 강서구 구랑동
1 26440-00002 압곡공원 근린공원 부산광역시 강서구 구랑동 1219 부산광역시 강서구 구랑동 1219 35.154655 128.854727 33756.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 1.837281 부산광역시 강서구 구랑동
2 26440-00003 서연정공원 소공원 부산광역시 강서구 대저1동 1330-7 부산광역시 강서구 대저1동 1330-7 35.216183 128.969558 646.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.254165 부산광역시 강서구 대저1동
3 26440-00004 용두공원 어린이공원 부산광역시 강서구 대저2동 1870-67 부산광역시 강서구 대저2동 1870-67 35.183679 128.956007 1620.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.402492 부산광역시 강서구 대저2동
4 26440-00005 새동내공원 어린이공원 부산광역시 강서구 대저2동 2407-1 부산광역시 강서구 대저2동 2407-1 35.174568 128.950612 1009.0 051-970-4536 2019-05-02 3360000 부산광역시 강서구 0.317648 부산광역시 강서구 대저2동
park_ok['시도'].value_counts()
경기도        3318
전라남도       1882
경상남도       1825
서울특별시      1744
충청남도       1723
전라북도       1137
경상북도        917
충청북도        898
울산광역시       887
인천광역시       675
부산광역시       653
강원도         647
대구광역시       586
대전광역시       497
광주광역시       429
제주특별자치도     246
세종특별자치시      70
강원            1
Name: 시도, dtype: int64
# '시도'가 '강원'인 데이터를 '강원도'로 수정한다.
park_ok['시도'][park_ok['시도'] == '강원'] = '강원도'
park_ok['시도'].value_counts()
경기도        3318
전라남도       1882
경상남도       1825
서울특별시      1744
충청남도       1723
전라북도       1137
경상북도        917
충청북도        898
울산광역시       887
인천광역시       675
부산광역시       653
강원도         648
대구광역시       586
대전광역시       497
광주광역시       429
제주특별자치도     246
세종특별자치시      70
Name: 시도, dtype: int64

시도별 공원 데이터 시각화

ggplot(park_ok, aes(x='경도', y='위도', color='시도')) \
    + geom_point(size=0.5) \
    + theme(text=element_text(family='NanumGothicCoding'), figure_size=[6, 8])

output_37_0

<ggplot: (189338420726)>
plt.figure(figsize=[8, 10])
sns.scatterplot(data=park_ok, x='경도', y='위도', hue='시도', s=10)
<AxesSubplot:xlabel='경도', ylabel='위도'>

output_38_1

공원 구분별 분포

ggplot(park_ok, aes(x='경도', y='위도', color='공원구분', size='공원면적비율')) \
    + geom_point() \
    + theme(text=element_text(family='NanumGothicCoding'), figure_size=[6, 8])

output_40_0

<ggplot: (189342326255)>
plt.figure(figsize=[8, 10])
sns.scatterplot(data=park_ok, x='경도', y='위도', hue='공원구분', size='공원면적비율', sizes=(10, 500))
<AxesSubplot:xlabel='경도', ylabel='위도'>

output_41_1

park_ok['공원구분'].value_counts()
어린이공원     9987
근린공원      4168
소공원       2647
문화공원       322
수변공원       301
기타         260
체육공원       230
역사공원       164
묘지공원        43
도시농업공원      13
Name: 공원구분, dtype: int64

어린이 공원을 제외한 공원 분포

ggplot(park_ok[park_ok['공원구분'] != '어린이공원'], aes(x='경도', y='위도', color='공원구분', size='공원면적비율')) \
    + geom_point() \
    + theme(text=element_text(family='NanumGothicCoding'), figure_size=[6, 8])

output_44_0

<ggplot: (-9223371847511614292)>
plt.figure(figsize=[8, 10])
sns.scatterplot(data=park_ok[park_ok['공원구분'] != '어린이공원'], x='경도', y='위도', hue='공원구분', size='공원면적비율', 
                sizes=(10, 500))
<AxesSubplot:xlabel='경도', ylabel='위도'>

output_45_1

시도별 공원 비율

# '시도'별 공원 개수를 계산한다.
# value_counts() 함수는 별도의 옵션을 지정하지 않으면 데이터 개수를 계산해서 내림차순으로 정렬해서 출력한다.
# 오름차순으로 정렬해서 출력하려면 ascending=True 옵션을 지정하면 된다.
park_do = pd.DataFrame(park_ok['시도'].value_counts()).reset_index()
park_do.columns = ['시도', '개수']
park_do
시도 개수
0 경기도 3318
1 전라남도 1882
2 경상남도 1825
3 서울특별시 1744
4 충청남도 1723
5 전라북도 1137
6 경상북도 917
7 충청북도 898
8 울산광역시 887
9 인천광역시 675
10 부산광역시 653
11 강원도 648
12 대구광역시 586
13 대전광역시 497
14 광주광역시 429
15 제주특별자치도 246
16 세종특별자치시 70
# value_counts() 함수는 별도의 옵션을 지정하지 않으면 데이터 개수를 계산하고 normalize=True 옵션을 지정하면 전체 개수에 대한
# 비율을 계산해서 출력한다.
park_normalize = pd.DataFrame(park_ok['시도'].value_counts(normalize=True)).reset_index()
park_normalize.columns = ['시도', '비율']
park_normalize
시도 비율
0 경기도 0.182961
1 전라남도 0.103777
2 경상남도 0.100634
3 서울특별시 0.096168
4 충청남도 0.095010
5 전라북도 0.062696
6 경상북도 0.050565
7 충청북도 0.049518
8 울산광역시 0.048911
9 인천광역시 0.037221
10 부산광역시 0.036008
11 강원도 0.035732
12 대구광역시 0.032313
13 대전광역시 0.027406
14 광주광역시 0.023656
15 제주특별자치도 0.013565
16 세종특별자치시 0.003860
# 시도별 개수와 개수의 비율 데이터를 병합한다.
# park_sido = park_do.merge(park_normalize, left_index=True, right_index=True) # 시도_x, 시도_y 열이 나타난다. 
park_sido = park_do.merge(park_normalize, left_on='시도', right_on='시도')
park_sido
시도 개수 비율
0 경기도 3318 0.182961
1 전라남도 1882 0.103777
2 경상남도 1825 0.100634
3 서울특별시 1744 0.096168
4 충청남도 1723 0.095010
5 전라북도 1137 0.062696
6 경상북도 917 0.050565
7 충청북도 898 0.049518
8 울산광역시 887 0.048911
9 인천광역시 675 0.037221
10 부산광역시 653 0.036008
11 강원도 648 0.035732
12 대구광역시 586 0.032313
13 대전광역시 497 0.027406
14 광주광역시 429 0.023656
15 제주특별자치도 246 0.013565
16 세종특별자치시 70 0.003860
ggplot(park_sido, aes(x='시도', y='개수')) \
    + geom_bar(stat='identity', fill='green') \
    + theme(text=element_text(family='NanumGothicCoding'), figure_size=[18, 8])

output_50_0

<ggplot: (189345861864)>
ggplot(park_sido, aes(x='시도', y='개수')) \
    + geom_bar(stat='identity', fill='green') \
    + theme(text=element_text(family='NanumGothicCoding'), figure_size=[10, 8], axis_text_x=element_text(rotation=45))

output_51_0

<ggplot: (189336376584)>
ggplot(park_sido, aes(x='시도', y='개수')) \
    + geom_bar(stat='identity', fill='green') \
    + coord_flip() \
    + theme(text=element_text(family='NanumGothicCoding'), figure_size=[10, 8])

output_52_0

<ggplot: (189340465128)>
plt.figure(figsize=[12, 8])
sns.barplot(data=park_sido, x='시도', y='개수')
<AxesSubplot:xlabel='시도', ylabel='개수'>

output_53_1

plt.figure(figsize=[12, 8])
plt.xticks(rotation=45)
sns.barplot(data=park_sido, x='시도', y='개수')
<AxesSubplot:xlabel='시도', ylabel='개수'>

output_54_1

plt.figure(figsize=[12, 8])
sns.barplot(data=park_sido, x='개수', y='시도')
<AxesSubplot:xlabel='개수', ylabel='시도'>

output_55_1

# https://plotnine.readthedocs.io/en/stable/tutorials/miscellaneous-order-plot-series.html
from pandas.api.types import CategoricalDtype
from plotnine.data import mpg
(ggplot(mpg)
 + aes(x='manufacturer')
 + geom_bar(size=20)
 + coord_flip()
 + labs(y='Count', x='Manufacturer', title='Number of Cars by Make')
)

output_57_0

<ggplot: (-9223371847514367123)>
# Determine order and create a categorical type
# Note that value_counts() is already sorted
manufacturer_list = mpg['manufacturer'].value_counts().index.tolist()
manufacturer_cat = pd.Categorical(mpg['manufacturer'], categories=manufacturer_list)

# assign to a new column in the DataFrame
mpg = mpg.assign(manufacturer_cat = manufacturer_cat)

(ggplot(mpg)
 + aes(x='manufacturer_cat')
 + geom_bar(size=20)
 + coord_flip()
 + labs(y='Count', x='Manufacturer', title='Number of Cars by Make')
)

output_58_0

<ggplot: (189340426076)>
park_list = park_ok['시도'].value_counts().index.tolist()
park_cat = pd.Categorical(park_ok['시도'], categories=park_list)
park_ok = park_ok.assign(park_cat = park_cat)
(ggplot(park_ok)
 + aes(x='park_cat')
 + geom_bar(size=20)
 + coord_flip()
 + labs(y='개수', x='시도', title='시도별 공원 분포수')
 + theme(text=element_text(family='NanumGothicCoding'), figure_size=[10, 8])
)

output_59_0

<ggplot: (-9223371847511513305)>

태그:

카테고리:

업데이트:

댓글남기기