Pandas와 Matplotlib을 이용해 약 천만명이 모여 살고 있는 서울시의 각 구별 인구수와 CCTV 설치 수를 시각화해 어느 구가 많이 또는 적게 설치되어 있는지 파악해볼 것이다.
데이터는 서울 열린 데이터 광장에서
서울시 자치구 년도별 CCTV 설치 현황
서울시 자치구별 연령별 인구
를 참고하시면 됩니다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from matplotlib import rc
rc('font', family='Arial Unicode MS')
CCTV_Seoul = pd.read_csv("/Users/gyol/Documents/ds_study/data/01. Seoul_CCTV.csv", encoding="utf-8")
CCTV_Seoul.head()
🧑🏻💻 앞으로 데이터프레임을 편의상
df
(DataFrame)라고 하겠다.
- 데이터 프레임의 첫 다섯줄을 보고 싶을 때는
df.head()
를 사용하면 된다.(기본이 5줄)- n개의 줄을 보고 싶을 때는
df.head(n)
- 끝에서부터 보고 싶으면
df.tail(n)
을 사용하면 된다.
pop_Seoul = pd.read_excel("/Users/gyol/Documents/ds_study/data/01. Seoul_Population.xls", header=2, usecols="B, D, G, J, N")
# 엑셀에서 2번째 행이 header, B,D,G,J,N열을 불러온다
pop_Seoul.head()
데이터프레임 열의 이름 바꾸기
pop_Seoul.drop([0], inplace = True)
pop_Seoul.rename(
columns={
pop_Seoul.columns[0]: "구별",
pop_Seoul.columns[1]: "인구수",
pop_Seoul.columns[2]: "한국인",
pop_Seoul.columns[3]: "외국인",
pop_Seoul.columns[4]: "고령자",
},inplace = True
)
pop_Seoul.head()
CCTV_Seoul.sort_values(by='소계',ascending=True).head(5) # 소계 열 오름차순
도봉구에 제일 적다는것을 확인할 수 있다.
CCTV_Seoul['최근증가율']=(
(CCTV_Seoul['2016년']+CCTV_Seoul['2015년']+CCTV_Seoul['2014년'])
/ CCTV_Seoul['2013년도 이전']
*100
)
CCTV_Seoul.sort_values(by='최근증가율',ascending=False).head(5)
13년에 비해 14,15,16년도 증가율은 종로구가 제일 크다는 것을 확인할 수 있다.
CCTV_Seoul.rename(columns={'기관명':'구별'},inplace=True)
CCTV_Seoul.head()
두 데이터를 '구별' 행으로 합쳐보겠다.
data_result = pd.merge(CCTV_Seoul, pop_Seoul, on='구별')
data_result.set_index('구별', inplace=True)
data_result.head()
필요없는 열은 지워보겠다.
del data_result['2013년도 이전']
del data_result['2014년']
del data_result['2015년']
del data_result['2016년']
data_result.head()
data_result['CCTV비율'] = data_result['소계']/data_result['인구수']
data_result['CCTV비율'] = data_result['CCTV비율'] * 100
data_result.sort_values(by='CCTV비율',ascending=False).head()
인구수 대비 CCTV가 많은 곳은 종로구가 가장 높고 그다음으로 용산구, 중구, 강남구, 금천구 순인것을 확인할 수 있다.
import matplotlib.pyplot as plt
%matplotlib inline
from matplotlib import rc
rc('font', family='Arial Unicode MS')
data_result['인구수'].plot(kind='bar', figsize=(10,10))
data_result['인구수'].plot(kind='barh', figsize=[10,10]);
이렇게만 보면 직관적인 판단이 어렵다.
data_result['소계'].sort_values().plot(
kind = 'barh',
grid = True,
title = '가장 CCTV가 많은 구',
figsize = (10, 10)
);
순서대로 나열을 하니 어느 구가 제일 많이 CCTV가 있는지 확인할 수 있었다.
plt.figure(figsize=(14,10))
plt.scatter(data_result['인구수'],data_result['소계'],s = 50)
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()
크지는 않지만 인구수가 증가하면 CCTV의 수도 증가하는 경향이 있는 것을 확인할 수 있다.
fp1 = np.polyfit(data_result['인구수'], data_result['소계'], 1) # 직선을 구성하기 위한 계수 계산
f1 = np.poly1d(fp1)
fx = np.linspace(100000, 700000, 100)
plt.figure(figsize=(14,10))
plt.scatter(data_result['인구수'],data_result['소계'],s = 50)
plt.plot(fx,f1(fx), ls='dashed', lw=3, color='g')
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()
경향성을 대변하는 회귀선을 그렸다. 이 선보다 위는 서울시 경향보다 좀더 많이 설치된 구이고, 아래는 경향보다 적게 설치된 구이다.
❓회귀선의 원리가 궁금하다면 클릭!
data_result['오차'] = data_result['소계'] - f1(data_result['인구수'])
df_sort_f = data_result.sort_values(by='오차', ascending= False)
df_sort_t = data_result.sort_values(by='오차', ascending= True)
df_sort_t.head()
from matplotlib.colors import ListedColormap
color_step = ['#e74c3c', '#2ecc71', '#95a5a6', '#2ecc71', '#3498db', '#3498db']
my_cmap = ListedColormap(color_step)
plt.figure(figsize=(14,10))
plt.scatter(data_result['인구수'],data_result['소계'],c = data_result['오차'],s = 50, cmap=my_cmap)
plt.plot(fx,f1(fx), ls='dashed', lw=3, color='grey')
for n in range(5):
plt.text(
df_sort_f['인구수'][n] * 1.02,
df_sort_f['소계'][n] * 0.98,
df_sort_f.index[n],
fontsize = 15
)
plt.text(
df_sort_t['인구수'][n] * 1.02,
df_sort_t['소계'][n] * 0.98,
df_sort_t.index[n],
fontsize = 15
)
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.colorbar()
plt.grid()
plt.show()
경향에 비해 설치 건수가 많은 점은 파란색, 낮는 점은 빨간색으로 표현했고, 각각 5개씩 높은 구와 낮은구가 어딘지 파악해보았다.