# -*- coding: utf-8 -*-
"""
Created on Thu Apr 23 09:49:21 2020

@author: admin
"""

'''
서울시 구별 CCTV 현황 분석하기

서울시 각 구별 CCTV 수를 파악하고,
인구대비 CCTV 비율을 파악해서 순위 비교

인구대비 CCTV의 평균치를 확인하고
그로부터 CCTV가 과하게 부족한 구를 확인

Python 기본 문법 / Pandas 와 Matplotlib의 기본적 사용법을 이용한 시각화
단순한 그래프 표현에서
한 단계 더 나아가 경향을 확인하고 시각화하는 기초 확인
 
'''
import pandas as pd
import numpy as np

# CCTV 데이터와 인구 데이터 합치고 분석하기

##CCTV 데이터 읽기
CCTV_Seoul = pd.read_csv('./data/01. CCTV_in_Seoul.csv', encoding='UTF-8')
#데이터프레임
CCTV_Seoul.head()

CCTV_Seoul.columns

CCTV_Seoul.columns[0]

#칼럼명 변경 : 기관명을 구별로 변경 
CCTV_Seoul.rename(columns={CCTV_Seoul.columns[0]:'구별'}, inplace=True)
CCTV_Seoul.head()


# 인구데이터 읽기 1
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls', encoding='UTF-8')
pop_Seoul.head()

#인구 데이터 읽기2 - 필요한 데이터만 선별하여 읽기
pop_Seoul = pd.read_excel('./data/01. population_in_Seoul.xls',
                          header=2, # 헤더 두 줄 건너 뛰고 나타내라
                          usecols='B, D, G, J, N', # 사용할 컬럼 지정
                          encoding='utf-8')

pop_Seoul.head()

#계라고 나오는 컬럼을 알기 쉬운 컬럼명으로 변경
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 데이터 파악하기
# 소계 순으로 정렬(오름차순)
CCTV_Seoul.sort_values(by='소계', ascending=True).head(5)
# 소계 순으로 정렬(내차순)
CCTV_Seoul.sort_values(by='소계', ascending=False).head(5)
#sort_values : 원본에 정렬순으로 저장되는 것은 아니다.


# 최근증가율 = (2016년+2015년+2014년)/2013년도 이전 * 100
CCTV_Seoul['최근증가율']=(CCTV_Seoul['2016년']+CCTV_Seoul['2015년']+ \
                     CCTV_Seoul['2014년']) / CCTV_Seoul['2013년도 이전'] * 100
    
    
CCTV_Seoul.sort_values(by='최근증가율', ascending=False).head()


#서울시 인구데이터 파악하기
pop_Seoul.head()

#첫번째 합계 행 삭제
pop_Seoul.drop([0],inplace=True)
pop_Seoul,head()

#'구별' 칼럼의 중복값 제거
pop_Seoul['구별'].unique()

#'구별' 칼럼의 NULL 값 확인
#isnull() : 널값의 행값과 널값을 인덱스 번호를 반환 시켜준다.
#     구별  인구수  한국인  외국인  고령자
#26  NaN  NaN  NaN  NaN  NaN
pop_Seoul[pop_Seoul['구별'].isnull()]

# '구별' 컬럼의 NULL값 있는 행 제거
pop_Seoul.drop([26],inplace=True)
pop_Seoul.head()

'''
데이터 분석
1.분석데이터 수집(R or python )
2.수집된 데이터 형식 확인 및 로컬 전처리
3.분석 prg에서 수집 데이터 읽기
4.읽은 데이터 확인 및 3차 전처리
'''

#외국인비율과 고령자 비율 추가
pop_Seoul['외국인비율']=pop_Seoul['외국인']/pop_Seoul['인구수']*100
pop_Seoul['고령자비율']=pop_Seoul['고령자']/pop_Seoul['인구수']*100
pop_Seoul.head()

# 각 칼럼 확인
pop_Seoul.sort_values(by='인구수', ascending=False).head()
pop_Seoul.sort_values(by='외국인', ascending=False).head()
pop_Seoul.sort_values(by='외국인비율', ascending=False).head()
pop_Seoul.sort_values(by='고령자', ascending=False).head()
pop_Seoul.sort_values(by='고령자비율', ascending=False).head()

# 시각화 작업을 위함 구이름('구별')을 index화
data_result.set_index('구별', inplace=True)
data_result.head()


###CCTV 데이터와 인구 데이터 합치고 분석하기

# 두개의 데이터프레임을 합할 경우 동일 컬럼명은 하나('구별')로 통일 된다.
data_result = pd.merge(CCTV_Seoul,pop_Seoul, on='구별') 
data_result.head() 

# CCTV에 대한 '소계' 컬럼을 제외한 나머지 CCTV 데이터 삭제
del data_result['2013년도 이전']
del data_result['2014년']
del data_result['2015년']
del data_result['2016년']
data_result.head()

#CCTV와 각 칼럼에 대한 상솬관계 분석
# 상관관계 함수 :np.corrcoef()
np.corrcoef(data_result['고령자비율'],data_result['소계'])
np.corrcoef(data_result['외국인비율'],data_result['소계'])
np.corrcoef(data_result['인구수'],data_result['소계'])
data_result.sort_values(by='소계', ascending=False).head(5)

#csv로 저장시켜주는 함수
data_result.to_csv('data_result.csv')
# 데이터 읽히는지 확인하기
pd.read_csv('data_result.csv', encoding='utf-8')

 

# CCTV와 인구현황 그래프로 분석하기

import platform
import pandas as pd
import numpy as np

# 폰트 설정(특히 한글부분)
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus']=False

data_result = pd.read_csv('data_result.csv', encoding='utf-8')

if platform.system() == 'Darwin':
    rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
    path = "c:/Windows/Fonts/malgun.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc('font', family=font_name)
else:
    print('Unknown system.... sorry')
    
# CCTV 비율을 구하고 그에 따른 시각화 작업
data_result['CCTV비율'] = data_result['소계'] / data_result['인구수'] * 100

data_result['CCTV비율'].sort_values().plot(kind='barh', grid=True, figsize=(10,10))
plt.show()

# 산점도(인구수와 소계)
plt.figure(figsize=(6,6))
plt.scatter(data_result['인구수'], data_result['소계'], s=50)
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()

# 인구수와 CCTV는 상관계수가 양의 값이므로 산점도와 직선
# 직선 구하기 (Polyfit을 이용한 회귀선)
# polyfit 함수를 이용해서 예측 모델 z의 계수를 생성
fp1 = np.polyfit(data_result['인구수'], data_result['소계'],1)
fp1

# 만들어진 예측 모델을 이용한 그래프 그리기
f1 = np.poly1d(fp1) # y축 데이터
fx = np.linspace(100000, 700000, 100) # x축 데이터

plt.figure(figsize = (10, 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()
'''인구수가 310000 정도일 때, cctv는 1100대가 적당하다'''

# 조금더 설득력 있는 자료 만들기
'''
직선이 전체 데이터의 대표값 역할을 한다면 
인구수가 300,000일경우 CCTV는 1100정도여야 한다는 결론
가독성 향상을 위해 오차를 계산할 수 있는 코드 작성후,
오차가 큰 순으로 데이터를 정렬
'''
fp1 = np.polyfit(data_result['인구수'], data_result['소계'],1)

f1 = np.poly1d(fp1) # y축 데이터
fx = np.linspace(100000, 700000, 100) # x축 데이터

data_result['오차'] = np.abs(data_result['소계']- f1(data_result['인구수']))
df_sort = data_result.sort_values(by = '오차', ascending =False)
df_sort.head()

#plot 크기 설정
plt.figure(figsize=(14,10))

#산점도
plt.scatter(data_result['인구수'],data_result['소계'],
            c =data_result['오차'], s=50)

#회귀선
plt.plot(fx,f1(fx),ls='dashed', lw=3, color='g')

#주요 10개 지역 구이름 출력
for n in range(10):
    plt.text(df_sort['인구수'][n]*1.02, df_sort['소계'][n]*0.98,
             df_sort.index[n], fontsize=15)

plt.xlabel('인구수')
plt.ylabel('인구당비율')
plt.colorbar() #오른쪽에 생상바
plt.grid() #가이드라인
plt.show()

 

# 강남 3구는 안전한가?

 

 

+ Recent posts