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가 너무 적은 구 들은 빨간색 마커로 송파구, 강서구, 중랑구, 광진구, 도봉구 이다.