새소식

데이터분석/다섯째주

EDA : 서울시 CCTV · 인구 현황(5) 경향파악 / 시각화 강조

  • -
728x90

목차

 

 

주제 : 인구 데이터와 CCTV는 상관관계가 있을까?

  1. 서울시 구별 CCTV 현황 데이터 확보 (Python, Pandas)
  2. 인구 현황 데이터 확보  (Python, Pandas)
  3. CCTV 데이터와 인구 형황 데이터 합치기  (Python, Pandas)
  4. 데이터 정리하고 정렬하기  (Python, Pandas)
  5. 그래프를 그릴 수 있는 능력 (Matplotlib)
  6. 전체적인 경향을 파악할 수 있는 능력 (Regression using Numpy)  ✔
  7. 그 경향에서 벗어난 데이터를 강조하는 능력 (Insight and Visualization)  

 

서울시 CCTV 현황과 인구 현황

  • 단순 CCTV 수와 인구대비 CCTV 비율을 볼때..
    CCTV 많은 구: 강남, 양천, 서초, 관악, 은평, 용산
    CCTV 비율이 높은 구: 종로, 용산, 중구가 1위 그룹
  •  비율로 데이터를 봐도 전체 경향과 함께 보지 않으면, 데이터를 제대로 이해시키기 어렵게 보인다. 

 

 

scatter 그래프 그리기 

import matplotlib.pyplot as plt

def drawScatter(col, label):
	plt.figure(figsize=(14, 10))
	plt.scatter(data_result[col[0]], data_result[col[1]], s=50)
	plt.xlabel(label[0])
	plt.ylabel(label[1])
	plt.grid()
	plt.show()

 

 

 

인구수와 CCTV 개수 전체 데이터 살펴보기

drawScatter(['인구수', '소계'], ['인구수' ,'CCTV'])

-- 출력 --

인구수가 많아질수록 CCTV 수가 높은 경향이 보여진다.
경향선을 그려보자.

 

 

 

경향선 : Numpy를 이용한 1차 직선 만들기

[ 절차 ]

  1.  numpy.polyfit( )     :  직선을 구성하기 위한 계수(y절편, 기울기) 계산
  2.  numpy.poly1d( )     :  polyfit으로 찾은 계수로 python에서 사용할 함수(방정식)로 만들어 준다.

전체 경향을 나타내는 1차식 직선의 계수(y절편, 기울기)를 polyfit 으로 계산해준다.

import numpy as np

fp1 = np.polyfit(data_result['인구수'], data_result['소계'], 1) #1차식, 직선
print(fp1)

-- 출력 --

array( [ 1.11155868e-03, 1.06515745e+03 ] )

 

polyfit으로 찾은 계수를 넣어서 함수로 완성해준다.

f1 = np.poly1d(fp1) #함수로 만들기, f1은 변수가 아니라 함수명이다.

 

함수에 데이터를 넣어서 전체 경향에 맞는 예측값 보기

# 인구수 400000 인 구에서 서울시의 전체 경향에 맞는 적당한 CCTV수를 알아보기
print( f1(400000) )

-- 출력 --

1509.7809252413335

 

경향선을 그리기 위해 X 데이터 생성

  • np.linspace(a, b, n)  :  a부터 b까지 n개의 등간격 데이터 생성
fx = np.linspace(100000, 700000, 100)

 

 

경향선까지 포함하여 그래프 그리기

def drawGraph2():
	plt.figure(figsize=(14, 10))
	plt.scatter(data_result['인구수'], data_result['소계'], s=50)
    
	# 경향선 그리기 : 등간경의 X 데이터, f1함수에 X데이터를 넣어 예측한 y 데이터
	plt.plot(fx, f1(fx), ls='dashed', lw=3, color='g')  
    
	plt.xlabel('인구수')
	plt.ylabel('CCTV')
	plt.grid()
	plt.show()

 

drawGraph2()

-- 출력 --

 

경향에 비해서 너무 많은 CCTV를 가진 구와 너무 적은 CCTV를 가진 구를 살펴보자.

 

 

 

경향에서 벗어난 데이터 강조하기

  • 경향선 = 예측값

경항(trend)과의 실제값의 오차가 많은 데이터(구)를 찾아보자.

  • 경향 : f1 함수에 해당 인구를 입력
  • 실제값(현재값) : '소계' 컬럼
  • 오차 : 실제값과 예측값의 차이 ( 실제값 - 예측값 )
# 인구수와 CCTV 개수 데이터로 1차식 경향선의 계수 계산하기
fp1 = np.polyfit(data_result['인구수'], data_result['소계'], 1)

# 1차식 경향선 계수로 함수 만들기
f1 = np.poly1d(fp1)

# 오차(실제값-예측값) 컬럼 추가
data_result['오차'] = data_result['소계'] - f1( data_result['인구수'] )

# 오차가 큰 데이터
# 내림차순, 경향 대비 CCTV를 많이 가진 구
df_sort_f = data_result.sort_values(by='오차', ascending=False) 

print( df_sort_f )

-- 출력 --

 

 

# 오차가 큰 데이터
# 내림차순, 경향 대비 CCTV를 적게 가진 구
df_sort_t = data_result.sort_values(by='오차', ascending=True) 

print( df_sort_t )

-- 출력 --

 

 

 

경향에서 벗어난 데이터 그래프에 표시하기

text( ) : 그래프에 글자 표시하는 명령

 plt.text(x 위치값, y 위치값, 표시할 텍스트, fontsize= )   

  • 글자가 마커에 겹치지 않도록 살짝 거리를 두려면,  x 위치값 * 1.02, y 위치값 * 0.98 을 하면 된다.
from matplotlib.pyplot import ListedColormap

# color map을 사용자 정의로 세팅
color_step = ['#e74c3c', '#2ecc71', '#98a5a6', '#2ecc71', '#3498db', '#3498db']
my_cmap = ListedColormap(color_step)

 

def drawGraph3():
	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')

	# 오차가 큰 상위 5개 구의 이름을 마커 옆에 표시
	# 구 이름이 마커에 겹치지 않도록 살짝 거리를 두게하는 의도로 1.02, 0.98 을 곱하였다.
	for n in range(5): 
		plt.text(
			df_soft_f['인구수'][n] * 1.02,  # 위치 x값
			df_soft_f['소계'][n] * 0.98,  # 위치 y값
			df_sort_f.index[n],
			fontsize=15
		)
		plt.text(
			df_soft_t['인구수'][n] * 1.02,  # 위치 x값
			df_soft_t['소계'][n] * 0.98,  # 위치 y값
			df_sort_t.index[n],
			fontsize=15
		)
        
	plt.xlabel('인구수')
	plt.ylabel('CCTV')
	plt.colorbar()
	plt.grid()
	plt.show()

 

drawGraph3()

-- 출력 --

경향 대비 CCTV가 너무 많은 구 들은 파란색 마커로 강남구, 양천구, 용산구 이다.
경향 대비 CCTV가 너무 적은 구 들은 빨간색 마커로 송파구, 강서구, 중랑구, 광진구, 도봉구 이다.

 

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.