본문 바로가기
  • 紹睿: 자유롭고 더불어 사는 가치있는 삶
Project/데이터 가지고 놀기

[서울시 도서관] 서울시 도서관 개수 시각화

by 징여 2018. 7. 11.
반응형
In [7]:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import folium
%matplotlib inline

도서관 데이터 가져오기¶

In [6]:
library = pd.read_excel('./data/library.xlsx', skiprows=7)
library.head()
Out[6]:
도서관명 주소 전화번호 팩스번호 위도 경도 홈페이지 휴관일 도서관코드
0 2.28도서관 대구광역시 중구 2·28길 9 053-257-2280 053-257-2284 35.857981 128.589620 http://www.228lib.or.kr/ 매주 월요일 / 법정공휴일(일요일을 제외한 관공서 공휴일), 도서관 및 기타 사정으... 127058.0
1 U보라작은도서관 경상남도 김해시 전하로176번길 71, 반도보라아파트 주민공동시설 2층 055-324-3335 - 35.223558 128.874226 http://lib.gimhae.go.kr/03city/07_14_01.asp 매주 일요일 / 법정공휴일, 임시공휴일 148096.0
2 가락몰도서관 서울 송파구 양재대로 932 NaN NaN 37.492994 127.110137 NaN NaN 111456.0
3 가수원도서관 대전광역시 서구 가수원로 91-11 042-288-4770 042-288-5937 36.301900 127.348812 http://www.seogu.go.kr/learning/gasuwonlib/ind... 매주 월요일 / 국경일, 정부에서 정한 공휴일, 도서관 사정으로 인한 휴관하는 날 125010.0
4 가양도서관 대전광역시 동구 우암로277번길 72 042-259-7081 042-628-8168 36.348977 127.445151 http://lib.donggu.go.kr/html/library/gayanglib/ 매주 월요일 / 국경일, 기타 원장이 필요하다고 인정되는 경우 125012.0

1. 서울에 있는 도서관만 걸러내보자¶

주소 앞부분이 '서울' 이거나 전화번호 앞부분을 02로 설정하면 될것같다.

nan 값 가져오기¶

isnull().any().any()

In [12]:
library['주소'].isnull().sum(), library['전화번호'].isnull().sum()
Out[12]:
(0, 47)

주소 null 값이 있는 애들은 0, 전화번호는 47건이나되니까 주소를 가지고 서울구역을 나누기로 마음 먹었따

In [14]:
library['주소'].str.split()[0]
Out[14]:
['대구광역시', '중구', '2·28길', '9']

2. str.split()¶

  • str.split()을 사용하게 되면, ' ' 띄어쓰기(default)를 기준으로 주소를 나누어 list형식으로 나타내준다.
  • str.split(' ', n=2, expand=True)를 이용하면, 시/ 구/ 세부주소 로 나눌 수 있다.
  • rename까지 해주면, 깔끔하게 columns 명까지 바꾸어 줄 수 있다.
In [26]:
library['주소'].str.split(' ', n=2, expand=True).rename(columns={0:'시', 1:'구', 2:'상세주소'}).head()
Out[26]:
상세주소
0 대구광역시 중구 2·28길 9
1 경상남도 김해시 전하로176번길 71, 반도보라아파트 주민공동시설 2층
2 서울 송파구 양재대로 932
3 대전광역시 서구 가수원로 91-11
4 대전광역시 동구 우암로277번길 72

하지만, 우리는 str.split(' ', n=n).str을 이용해 바로 column을 추가해줄거임!

In [29]:
library['시'], library['구'], library['상세주소'] = library['주소'].str.split(' ', n=2).str
library.tail()
Out[29]:
도서관명 주소 전화번호 팩스번호 위도 경도 홈페이지 휴관일 도서관코드 상세주소
684 효목2동작은도서관 대구광역시 동구 화랑로25길 45 053-662-3794 - 35.878129 128.641231 http://www.donggu-lib.kr/ 매주 토요일, 일요일 / 관공서 공휴일 127048.0 대구광역시 동구 화랑로25길 45
685 휘경어린이도서관 서울특별시 동대문구 망우로18가길 38 02-2248-1959 02-2248-1969 37.588681 127.060597 http://www.l4d.or.kr/ddmeach/index.php?libCho=MJ 매주 월요일 / 법정공휴일, 도서관 필요에 의해 관장이 정하는 날 111446.0 서울특별시 동대문구 망우로18가길 38
686 흥해읍 내맏이작은도서관 경상북도 포항시 북구 흥해읍 도음로877번길 9 054-262-3997 - 36.080530 129.329930 http://phlib.pohang.go.kr/ 매주 월요일, 일요일 / 법정공휴일 147147.0 경상북도 포항시 북구 흥해읍 도음로877번길 9
687 흥해읍 어리골작은도서관 경상북도 포항시 북구 흥해읍 달전로 291 054-262-3996 - 36.070460 129.333770 http://phlib.pohang.go.kr/ 매주 월요일, 일요일 / 법정공휴일 147148.0 경상북도 포항시 북구 흥해읍 달전로 291
688 흥해읍 참새미작은도서관 경상북도 포항시 북구 흥해읍 달전로 365 054-262-3002 - 36.076142 129.339163 http://phlib.pohang.go.kr/ 매주 월요일, 일요일 / 법정공휴일 747005.0 경상북도 포항시 북구 흥해읍 달전로 365

3. 서울 데이터만 뽑아내기¶

서울과 서울특별시로 나누어져있기 때문에, str.match('서울')를 이용하여 서울이 들어간 곳을 '서울특별시'로 통일해주자.

In [43]:
print(len(library[library['시'].str.match('서울')]))
library[library['시'].str.match('서울')].head()
155
Out[43]:
도서관명 주소 전화번호 팩스번호 위도 경도 홈페이지 휴관일 도서관코드 상세주소
2 가락몰도서관 서울 송파구 양재대로 932 NaN NaN 37.492994 127.110137 NaN NaN 111456.0 서울 송파구 양재대로 932
9 갈현1동문화의집 서울특별시 은평구 갈현로 301 NaN NaN 37.623651 126.914473 NaN NaN 711308.0 서울특별시 은평구 갈현로 301
10 강남구립논현도서관 서울특별시 강남구 학동로43길 17 02-3443-7650 02-542-6459 37.517333 127.037200 http://nhlib.gangnam.go.kr/ 매월 둘째주, 넷째주 화요일 / 일요일을 제외한 법정공휴일 111070.0 서울특별시 강남구 학동로43길 17
11 강남구립대치도서관 서울특별시 강남구 삼성로 212, 은마아파트 복지상가 2층 215호 02-565-6666 02-554-6666 37.495383 127.063706 http://dchlib.gangnam.go.kr/ 매월 둘째주, 넷째주 화요일 / 법정공휴일 111039.0 서울특별시 강남구 삼성로 212, 은마아파트 복지상가 2층 215호
12 강남구립도곡정보문화도서관 서울특별시 강남구 도곡로18길 57 02-2176-0783 02-529-0377 37.488182 127.038923 http://dogoklib.gangnam.go.kr/ 매월 첫째주, 셋째주 월요일 / 법정공휴일, 관장이 필요하다고 인정하는 날 111347.0 서울특별시 강남구 도곡로18길 57

3-1. df.replce(to_replace=['Abas'], values='A', inplace=True)를 이용하여 문자를 대체할 수 있다.¶

In [65]:
library['시'].replace(
    to_replace=['서울'],
    value='서울특별시',
    inplace=True
)
len(library[library['시'] == '서울'])
Out[65]:
0
In [67]:
library_seoul = library[library['시']=='서울특별시']
print(library_seoul.shape, library.shape)
library_seoul.head()
(155, 12) (689, 12)
Out[67]:
도서관명 주소 전화번호 팩스번호 위도 경도 홈페이지 휴관일 도서관코드 상세주소
2 가락몰도서관 서울 송파구 양재대로 932 NaN NaN 37.492994 127.110137 NaN NaN 111456.0 서울특별시 송파구 양재대로 932
9 갈현1동문화의집 서울특별시 은평구 갈현로 301 NaN NaN 37.623651 126.914473 NaN NaN 711308.0 서울특별시 은평구 갈현로 301
10 강남구립논현도서관 서울특별시 강남구 학동로43길 17 02-3443-7650 02-542-6459 37.517333 127.037200 http://nhlib.gangnam.go.kr/ 매월 둘째주, 넷째주 화요일 / 일요일을 제외한 법정공휴일 111070.0 서울특별시 강남구 학동로43길 17
11 강남구립대치도서관 서울특별시 강남구 삼성로 212, 은마아파트 복지상가 2층 215호 02-565-6666 02-554-6666 37.495383 127.063706 http://dchlib.gangnam.go.kr/ 매월 둘째주, 넷째주 화요일 / 법정공휴일 111039.0 서울특별시 강남구 삼성로 212, 은마아파트 복지상가 2층 215호
12 강남구립도곡정보문화도서관 서울특별시 강남구 도곡로18길 57 02-2176-0783 02-529-0377 37.488182 127.038923 http://dogoklib.gangnam.go.kr/ 매월 첫째주, 셋째주 월요일 / 법정공휴일, 관장이 필요하다고 인정하는 날 111347.0 서울특별시 강남구 도곡로18길 57

총 689개의 도서관중 155개의 서울 도서관들이 뽑혔다.

4. 위도와 경도를 이용하여 folium 지도에 뿌려주기¶

In [73]:
seoul = library_seoul.set_index('도서관명')
seoul.head()
Out[73]:
주소 전화번호 팩스번호 위도 경도 홈페이지 휴관일 도서관코드 상세주소
도서관명
가락몰도서관 서울 송파구 양재대로 932 NaN NaN 37.492994 127.110137 NaN NaN 111456.0 서울특별시 송파구 양재대로 932
갈현1동문화의집 서울특별시 은평구 갈현로 301 NaN NaN 37.623651 126.914473 NaN NaN 711308.0 서울특별시 은평구 갈현로 301
강남구립논현도서관 서울특별시 강남구 학동로43길 17 02-3443-7650 02-542-6459 37.517333 127.037200 http://nhlib.gangnam.go.kr/ 매월 둘째주, 넷째주 화요일 / 일요일을 제외한 법정공휴일 111070.0 서울특별시 강남구 학동로43길 17
강남구립대치도서관 서울특별시 강남구 삼성로 212, 은마아파트 복지상가 2층 215호 02-565-6666 02-554-6666 37.495383 127.063706 http://dchlib.gangnam.go.kr/ 매월 둘째주, 넷째주 화요일 / 법정공휴일 111039.0 서울특별시 강남구 삼성로 212, 은마아파트 복지상가 2층 215호
강남구립도곡정보문화도서관 서울특별시 강남구 도곡로18길 57 02-2176-0783 02-529-0377 37.488182 127.038923 http://dogoklib.gangnam.go.kr/ 매월 첫째주, 셋째주 월요일 / 법정공휴일, 관장이 필요하다고 인정하는 날 111347.0 서울특별시 강남구 도곡로18길 57
In [74]:
map = folium.Map(location=[37.5502, 126.982], zoom_start=11)
for i in seoul.index:
    folium.Marker([seoul['위도'][i],
                  seoul['경도'][i]]).add_to(map)
map
Out[74]:
In [78]:
seoul_gu = list(set(seoul['구']))
print(seoul_gu)
['관악구', '은평구', '동작구', '동대문구', '노원구', '성동구', '성북구', '종로구', '강서구', '영등포구', '마포구', '강남구', '강북구', '중구', '중랑구', '송파구', '서대문구', '용산구', '서초구', '구로구', '광진구', '강동구', '도봉구', '양천구']
In [89]:
seoul[seoul['구']=='관악구'].shape[0]
Out[89]:
6
In [97]:
gu_dict = {}
for gu in seoul_gu:
    gu_dict[gu] = seoul[seoul['구']==gu].shape[0]
print(gu_dict)
{'관악구': 6, '은평구': 17, '동작구': 1, '동대문구': 11, '노원구': 1, '성동구': 6, '성북구': 9, '종로구': 3, '강서구': 9, '영등포구': 1, '마포구': 2, '강남구': 27, '강북구': 7, '중구': 5, '중랑구': 4, '송파구': 13, '서대문구': 1, '용산구': 2, '서초구': 19, '구로구': 2, '광진구': 4, '강동구': 2, '도봉구': 2, '양천구': 1}
In [139]:
gu = pd.DataFrame.from_dict(gu_dict, orient='index')
gu.columns = ['개수']
gu.T
Out[139]:
관악구 은평구 동작구 동대문구 노원구 성동구 성북구 종로구 강서구 영등포구 ... 중랑구 송파구 서대문구 용산구 서초구 구로구 광진구 강동구 도봉구 양천구
개수 6 17 1 11 1 6 9 3 9 1 ... 4 13 1 2 19 2 4 2 2 1

1 rows × 24 columns

5. 서울 인구수 정리하기¶

In [122]:

pop_seoul = pd.read_excel('./data/population_in_Seoul.xls', header=2, parse_cols='B, D, G, J, N', encoding='utf-8') pop_seoul.head()

Out[122]:
자치구 계.1 계.2 65세이상고령자
0 합계 10158411.0 9891448.0 266963.0 1353486.0
1 종로구 164640.0 155109.0 9531.0 26034.0
2 중구 134174.0 125332.0 8842.0 21249.0
3 용산구 243922.0 228960.0 14962.0 36727.0
4 성동구 312933.0 304879.0 8054.0 40902.0

column 이름 변경하기¶

df.rename(columns={'자치구':'구', '계':'인구수', '계.1':'한국인', '계.2':'외국인', '65세이상고령자':'고령자'}, inplace=True)

In [124]:
pop_seoul.rename(columns={'자치구':'구', '계':'인구수', '계.1':'한국인', '계.2':'외국인', '65세이상고령자':'고령자'}, inplace=True)
pop_seoul=pop_seoul[1:]
pop_seoul.head()
Out[124]:
인구수 한국인 외국인 고령자
1 종로구 164640.0 155109.0 9531.0 26034.0
2 중구 134174.0 125332.0 8842.0 21249.0
3 용산구 243922.0 228960.0 14962.0 36727.0
4 성동구 312933.0 304879.0 8054.0 40902.0
5 광진구 372414.0 357743.0 14671.0 43579.0

6. 서울 인구별 도서관 비율 구하기¶

인구/ 도서관개수 합치기

In [129]:
pop_seoul = pop_seoul[0:25]
In [140]:
gu = gu.reset_index()
gu.columns = ['구', '도서관개수']
gu.head()
Out[140]:
도서관개수
0 관악구 6
1 은평구 17
2 동작구 1
3 동대문구 11
4 노원구 1
In [141]:
data_result = pd.merge(pop_seoul, gu, on='구')
data_result.head()
Out[141]:
인구수 한국인 외국인 고령자 도서관개수
0 종로구 164640.0 155109.0 9531.0 26034.0 3
1 중구 134174.0 125332.0 8842.0 21249.0 5
2 용산구 243922.0 228960.0 14962.0 36727.0 2
3 성동구 312933.0 304879.0 8054.0 40902.0 6
4 광진구 372414.0 357743.0 14671.0 43579.0 4

6-1.도서관개수 시각화¶

폰트 설정

In [151]:
from matplotlib import font_manager, rc

rc('font', family='AppleGothic')
plt.rcParams['axes.unicode_minus'] = False
In [153]:
data_result.set_index('구')['도서관개수'].sort_values().plot(kind='barh', grid='True', figsize=(10, 10))
Out[153]:
<matplotlib.axes._subplots.AxesSubplot at 0x109610e80>

6-2.도서관 비율¶

In [154]:
data_result['도서관비율'] = data_result['도서관개수']/data_result['인구수']*100
data_result.set_index('구')['도서관비율'].sort_values().plot(kind='barh', grid='True', figsize=(10, 10))
Out[154]:
<matplotlib.axes._subplots.AxesSubplot at 0x109fba898>

6-4. scatter로 표현하기¶

In [164]:
plt.figure(figsize=(7, 7))
plt.scatter(data_result['인구수'], data_result['도서관개수'], s= 30)
for i in data_result['구']:
    plt.text(data_result[data_result['구']==i]['인구수'], data_result[data_result['구']==i]['도서관개수'], i)
plt.xlabel('인구수')
plt.xlabel('도서관개수')
plt.grid()
plt.show()
In [166]:
result = data_result.set_index('구')
result.head()
Out[166]:
인구수 한국인 외국인 고령자 도서관개수 도서관비율
종로구 164640.0 155109.0 9531.0 26034.0 3 0.001822
중구 134174.0 125332.0 8842.0 21249.0 5 0.003727
용산구 243922.0 228960.0 14962.0 36727.0 2 0.000820
성동구 312933.0 304879.0 8054.0 40902.0 6 0.001917
광진구 372414.0 357743.0 14671.0 43579.0 4 0.001074
In [174]:

import json geo_str = json.load(open('./data/02. skorea_municipalities_geo_simple.json', encoding='utf-8'))

도서관 개수별 시각화¶

In [175]:
map = folium.Map(location=[37.5502, 126.982], zoom_start=11)
map.choropleth(geo_data=geo_str,
              data=result['도서관개수'],
              columns=[result.index, result['도서관개수']], 
              fill_color='YlGnBu',
              key_on='feature.id')
map
Out[175]:

도서관 비율 시각화¶

In [173]:
map2 = folium.Map(location=[37.5502, 126.982], zoom_start=11)
map2.choropleth(geo_data=geo_str,
              data=result['도서관비율'],
              columns=[result.index, result['도서관비율']], 
              fill_color='YlGnBu',
              key_on='feature.id')
map2
Out[173]:


데이터는 정보나루(https://www.data4library.kr/libDataL)에서 다운받아 사용했다.

library.xlsx


반응형

댓글