파이썬/머신러닝

[머신러닝] 서울시 CCTV현황으로 선형회귀 구하기

취준생코린이 2021. 6. 4. 17:53
728x90

 

먼저 데이터 분석과 전처리부터 한후 선형회귀를 구할거다.

 

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

  • 서울시 각 구별 CCTV수 파악
  • 인구대비 CCTV 비율을 파악해서 순위매기기
  • 인구대비 CCTV의 예측치를 확인하고, CCTV가 부족한 구 확인

 

# numpy : 고성능 과학계산을 위한 라이브러리, 다차원 데이터
# pandas : 데이터를 표현식으로 보여준다. 1,2차원 데이터
# matplotlib : 데이터 시각화
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

1. csv파일 읽어오기 - 서울시 구별 CCTV현황

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

# 기본값으로 5개를 불러옴
cctvSeoul.head()

2. 엑셀(xls)파일 읽기 - 서울시 인구 현황

# 한글 인코딩 종류 : utf-8, euc-kr, cp949

popSeoul = pd.read_excel('population_in_Seoul.xls')
popSeoul.head()

 

3.데이터 전처리

# cctv데이터 컬럼명 수정
# 기관명 > 구별
# rename({바꿀 값 : 바뀔 값}) : 컬럼명 바꾸기

# 서울시 cctv데이터의 기관명을 구별로 바꾸자

cctvSeoul.rename(columns = {cctvSeoul.columns[0]:"구별"}) # 값을 출력만함

# 전처리된 값을 저장하는 방법 2가지
# 1. 동일 변수에 출력값 저장하기
# 1. cctvSeoul = cctvSeoul.rename(columns = {cctvSeoul.columns[0]:"구별"})
# 2. inplace = True속성 사용하기 : 값을 출력하는거에서 저장하는거로 바뀐다
# 2. inplace속성이 있는 함수가 있고 없는 함수가 있다. 없으면 사용불가
# 2. cctvSeoul.rename(columns = {cctvSeoul.columns[0]:"구별"}, inplace = True)
cctvSeoul.rename(columns = {cctvSeoul.columns[0]:"구별"}, inplace = True)
cctvSeoul.head()

# pop_Seoul 데이터 수정
# 받아올 범위 지정하기
# header : 시작할 행(row)선택
# usecols : 가져올 column선택

popSeoul = pd.read_excel('population_in_Seoul.xls',
                                header = 2,
                                usecols = 'B, D, G, J, N')
popSeoul.head()

# popSeoul 컬럼명 바꾸기 
# 자치구 -> 구별
# 계 -> 인구수
# 계.1 - > 한국인
# 계.2 -> 외국인
# 65세 이상의 고령자 -> 고령자
# {'자치구':'구별', '계':'인구수'}
popSeoul.rename(columns = {popSeoul.columns[0]:'구별',
                                  popSeoul.columns[1]:'인구수',
                                  popSeoul.columns[2]:'한국인',
                                  popSeoul.columns[3]:'외국인',
                                  popSeoul.columns[4]:'고령자'},
                       inplace=True)
popSeoul.head()

 

cctv가 가장 적은 구와 가장 많은 구를 확인

# cctv가 가장 적은 구부터 확인
# sort_values : 컬럼안에 값을 기준으로 정렬
# by 속성에 기준이 되는 컬럼 입력
# 기본 정렬값은 오름차순 
cctvSeoul.sort_values(by='소계')
# cctvSeoul.min()

# cctv가 가장 많은 구부터 확인
# ascending=False를 넣으면 내림차순
cctvSeoul.sort_values(by='소계', ascending=False)
# cctvSeoul.max()

 

최근 3년동안 CCTV가 많이 설치된 지역을 알아보자

# '최근 3년 생성 갯수'
# 컬럼값 2014 + 2015 + 2016

# 컬럼 생성
# 변수명['생성컬럼명'] = 컬럼에 들어갈 값
# cctvSeoul['최근 3년 생성 갯수'] = cctvSeoul['2014년']+cctvSeoul['2015년']+cctvSeoul['2016년']
cctvSeoul['최근 3년 생성 갯수'] = cctvSeoul.iloc[:,3]+cctvSeoul.iloc[:,4]+cctvSeoul.iloc[:,5]

cctvSeoul

최근 3년 CCTV증가율

    1. '최근 3년 증가율' 컬럼 생성
    1. 최근 3년 CCTV 증가갯수 / 2013년 이전 CCTV 갯수
    1. 어떤 구에서 가장 많은 비율로 cctv가 증가했는지 알아보기

 

data = cctvSeoul['최근 3년 생성 갯수']/cctvSeoul['2013년도 이전'] * 100
cctvSeoul['최근 3년 증가율'] = data

cctvSeoul.sort_values(by='최근 3년 증가율', ascending= False)

 

서울시 인구 데이터 파악

cctvSeoul.shape

popSeoul.shape

popSeoul.columns

# unique() : 중복제거
cctvSeoul['구별'].unique()

popSeoul['구별'].unique()

# set : 집합자료형
# 순서가 없음
# 중복을 허용하지 않는다.
set(popSeoul['구별']) - set(cctvSeoul['구별'])

# popSeoul에는 있고 cctv_seoul에는 없는 데이터가 있을 수 있으니 확인해보자
set(cctvSeoul['구별']) - set(popSeoul['구별'])
# set()이 뜬거보니 popSeoul에는 있고 cctvSeoul에는 없는 데이터가 없나보다.

 

popSeoul['구별']에서 nan값과 합계값이 있는 행 삭제

# 구별컬럼에 합계값은 True 합계가 아닌값은 False
# Boolean값으로 변환
popSeoul['구별'] == '합계'

# Boolean인덱싱을 통해서 합계 값이 있는 행 출력
# Boolean인덱싱사용시 True값은 출력하고 False값은 출력하지 않는다.
popSeoul[popSeoul['구별'] == '합계']

# '구별' 컬럼에 값이 '합계'인 행의 인덱스 번호를 확인하기 위해 출력
# 출력하는 이유는 인덱스를 아래에서 삭제하기위해 번호를 확인한거다.
popSeoul[popSeoul['구별'] == '합계'].index

# drop함수
# drop(행번호) : 행삭제

# [0]번 인덱스를 가진행 삭제
# 즉, '구별'컬럼에 값이 '합계'인 행 삭제
popSeoul.drop([0], inplace=True)

# 결측치 제거 -> isnull()를 사용
# 결측치 : True
# 결측치가 아닌값 : False로 반환한다.
popSeoul[popSeoul['구별'].isnull()].index 
# 위의 코드는 블리언인덱싱을 하면 True인 값만 반환되니 결측치만 반환된거다.

# 지울 인덱스 번호를 delIndex에 담는다.
delIndex = popSeoul[popSeoul['구별'].isnull()].index

popSeoul.drop(delIndex, inplace= True)

popSeoul

 

구별 컬럼을 기준으로 데이터 합치기

# 데이터 프레임을 합치는 함수
# concat : 행,열을 기준으로 데이터 프레임을 합침
# merge : 행,열 속의 값을 기준으로 데이터 프레임을 합침
dataMerge = pd.merge(cctvSeoul, popSeoul, on='구별')
dataMerge.head()

 

인구대비 cctv비율

  • '인구대비 cctv 비율' 컬럼 생성
  • dataMarge에서 소계 / 인구수 값 대입
  • '인구대비 cctv 비율' 순위매기기
dataMerge['인구대비 cctv 비율'] = dataMerge.iloc[:,1]/ dataMerge.iloc[:,8] * 100

# 인구대비 cctv비율의 순위 생성
dataMergeSort = dataMerge.sort_values(by='인구대비 cctv 비율', ascending= False)
dataMergeSort['순위'] = 0

for i in range(len(dataMergeSort)):
    dataMergeSort.iloc[i,13] = i+1
    
dataMergeSort.head()

# sort_index() : 행 인덱스 정렬
dataMergeSort.sort_index().head()

 

 

인구대비 cctv의 예측치를 확인하고 , cctv가 부족한 구 확인

# 구별 멀럼을 인덱스로 만들기
# set_index('인덱스로 만들 컬럼 이름')

# inplace=True : 결과값을 원본에 그대로 반영 
# inplace= False : 결과값을 원본에 반영안함
dataMerge.set_index('구별', inplace=True)

# 인구수 대비 cctv수 시각화
# 왼쪽위로 갈수옥 인구수 대비 cctv가 적다.
# 오른쪽 아래로 갈수록 인구수 대비 cctv가 많다.
# x축 : cctv수, y축 : 인구수
plt.scatter(dataMerge['소계'],dataMerge['인구수'])
plt.show()

 

from matplotlib import rc
rc('font',family='Malgun Gothic')
# rc('font',family='Malgun Gothic')를 써야 matplotlib에서 한글 폰트를 지원해준다.

plt.figure(figsize= (15,8))
plt.barh(dataMerge.index, dataMerge['인구대비 cctv 비율'])
plt.show()

 

plt.figure(figsize= (15,8))
plt.bar(dataMerge.index, dataMerge['인구대비 cctv 비율'])
plt.show()

 

dataMerge.sort_values(by='인구대비 cctv 비율', ascending=False, inplace= True)

plt.figure(figsize= (15,8))
plt.bar(dataMerge.index, dataMerge['인구대비 cctv 비율'])
plt.show()

 

인구수 대비 CCTV비율 예측값 만들기

# 머신러닝 모델 받아오기
from sklearn.linear_model import LinearRegression
linear_model = LinearRegression()
# LinearRegression() : 선형회귀

# 학습하기
# fit(x, y)
# fit() 메서드는 선형 회귀 모델에 필요한 두 가지 변수를 전달하는 거다.
#기울기: line_fitter.coef_
#절편: line_fitter.intercept_

linear_model.fit(dataMerge[['인구수','인구대비 cctv 비율']], 
                 dataMerge[['소계']])
                 
# 학습한 값 확인하기
print('값1 :', linear_model.coef_) # 기울기
print('값2 :', linear_model.intercept_) # 절편

# predict : 예측하기
# predict(새로운 x값)을 하면 x값에 맞는 y값을 출력해준다. 
linear_model.predict( [[6516354654, 55555],[564, 464]] )

 

# 선형회귀 그래프 그리기
linear_model.fit(dataMerge[['인구수']], 
                 dataMerge[['소계']])

plt.scatter(dataMerge['인구수'],dataMerge['소계'])

plt.plot(dataMerge['인구수'], dataMerge['소계'], 'o')
plt.plot(dataMerge['인구수'],linear_model.predict(dataMerge['인구수'].values.reshape(-1,1)))
plt.show()
# 그래프를 보면 이해하기 더 쉽다.
# predict로 x에 새로운 값을 넣으면 직선이 예측모형인데 그직선이 지나는 절편을 알려주는 것이다.
# 그리고 점이 실제 데이터 값이다.
# 점과 직선 사이데 오차가 존재한다.

 

728x90