서울시 구역별 인구수 대비 CCTV 분석
데이터출처 : 서울열린데이터광장
- 데이터 확보&읽기
- 데이터 가공&정리
- 데이터 시각화
- 데이터 분석
프로젝트 세부절차
- 서울시 구별 CCTV 현황 데이터 확보
- 인구 현황 데이터 확보
- CCTV 데이터와 인구 현황과 데이터 합치기
- 데이터 정리 및 정렬
- 데이터 시각화(그래프)
- 전제적인 경향 파악
- 이상치 강조
- 데이터 분석하기
데이터 확보
'서울열린데이터광장'의 데이터를 pandas로 읽는다
해당 과정에서는 강사님이 준비해주신 데이터를 기반으로 한다
데이터 읽기
📝입력
# 서울CCTV 데이터 읽기
import pandas as pd
CCTV_Seoul = pd.read_csv("../data/01. Seoul_CCTV.csv")
CCTV_Seoul.rename(columns={CCTV_Seoul.columns[0]: "구별"}, inplace=True)
# 서울인구수 데이터 읽기
# 엑셀을 확인하여 필요한 칼럼만 읽어온다
pop_Seoul = pd.read_excel("../data/01. Seoul_Population.xls", header=2, usecols = "B, D, G, J, N")
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["최근증가율"] = (
(CCTV_Seoul["2014년"] + CCTV_Seoul["2015년"] + CCTV_Seoul["2016년"])/ CCTV_Seoul["2013년도 이전"] * 100
)
# 데이터 확인
# CCTV_Seoul.sort_values(by="최근증가율", ascending=False).head()
pop_Seoul.drop([0], axis=0, inplace=True)
pop_Seoul["외국인비율"] = pop_Seoul['외국인'] / pop_Seoul['인구수'] * 100
pop_Seoul["고령자비율"] = pop_Seoul['고령자'] / pop_Seoul['인구수'] * 100
# 데이터 확인
# pop_Seoul.sort_values(by="고령자비율", ascending=False).head()
# 데이터 합치기 및 불필요데이터 제거
data_result = pd.merge(CCTV_Seoul, pop_Seoul, on='구별')
del data_result['2013년도 이전']
del data_result['2014년']
data_result.drop(['2015년', '2016년'], axis=1, inplace=True)
data_result.set_index('구별', inplace=True)
data_result['CCTV비율'] = data_result['소계'] / data_result['인구수'] * 100
# 데이터 확인
# data_result.sort_values(by='CCTV비율', ascending=False).head()
🧾출력 : 최근증가율
🧾출력 : 고령자비율
🧾출력 : CCTV비율
CCTV비율 시각화
📝입력
import matplotlib.pyplot as plt
from matplotlib import rc
plt.rcParams["axes.unicode_minus"]= False # 마이너스부호때문에 한글이 깨질수 있어서 하는 설정
rc("font", family="MalGun Gothic") # Windows: 맑은고딕, Mac: Arial Unicode MS
%matplotlib inline
def drawGraph():
data_result["CCTV비율"].sort_values().plot(
kind="barh",
grid=True,
title="구역별 CCTV비율",
figsize=(7, 7)
)
drawGraph()
🧾출력
인구수&CCTV데이터와 경향선, 이상치 시각화
📝입력
# 데이터저장하기
data_result.to_csv("../data/0.1 CCTV_result.csv", sep=",", encoding='utf-8')
# 경향선 그리기
fp1 = np.polyfit(data_result['인구수'], data_result['소계'], 1)
f1 = np.poly1d(fp1)
fx = np.linspace(100000, 700000, 100)
# 오차파악
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)
# 이상치 강조를 위한 색상설정
from matplotlib.colors import ListedColormap
color_step = ['#e74c3c', '#2ecc71', '#95a9a6', '#2ecc71', '#3498db', '#3489db'] # 색상코드값
my_cmap = ListedColormap(color_step)
# 데이터 시각화
def drawGraph():
plt.figure(figsize=(10,8))
plt.scatter(data_result['인구수'], data_result['소계'],
s=25, c=data_result['오차'], cmap=my_cmap)
plt.plot(fx, f1(fx), ls='dashed', lw=3, color='g')
# 이상치 이름 표기
for n in range(5):
# 상위 5개
plt.text(
df_sort_f['인구수'][n] * 1.02,
df_sort_f['소계'][n] * 0.98,
df_sort_f.index[n],
fontsize=10,
)
# 하위 5개
plt.text(
df_sort_t['인구수'][n] * 1.02,
df_sort_t['소계'][n] * 0.98,
df_sort_t.index[n],
fontsize=10,
)
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.colorbar()
plt.grid()
plt.show()
drawGraph()
🧾출력
🧾0.1 CCTV_result.csv
일반적인 상식관점 : 인구수가 많으면 CCTV도 많다
서울시는 양의 상관관계를 가지고 있다
CCTV의 주목적과 기능을 고려하였을 때, 단순히 인구수만 고려하여 분석하는 것은 바람직하지 못하다
- CCTV목적 : 범죄예방, 감시, 인재(人災)예방 등
- CCTV기능 : CCTV가 보는 공간만 관측가능
(장애물이 적은 평지->소수로 충분)
(장애물이 많은 골목길->다수필요)
Part 04. EDA&Web Crawling Project의 서울시CCTV분석