1 개요

1.1 주제선정이유

library(tidyverse)
library(leaflet)
mymap = leaflet() %>% addTiles()

election  = geojsonio::geojson_read("election.json", what = "sp")

# 지도에 색을 입히기 위해서 파레트 생성
pal = colorFactor(c("#0D7440", "#2A88C5",  "#C10D0D"), c("국민의당", "더불어민주당","새누리당"))

# 툴팁에 담을 정보 생성
labs = lapply(seq(nrow(election@data)), function(i) {
  paste0( '<p><b>', election@data[i, "선거구"]," : ",election@data[i, "읍면동명"], '</b></p><p>', 
          "<b>당선 : ", election@data[i, "당선"], '</b><p></p>', 
          "국민의당 : ", election@data[i, "국민의당"],'</p><p>', 
          "더불어민주당 : ", election@data[i, "더불어민주당"], '</p><p>',
          "새누리당 : ", election@data[i, "새누리당"], '</p>') 
})

# 선거구 경계 생성
election_gu = maptools::unionSpatialPolygons(election, election$선거구)

poly2 = leaflet(election) %>%
  addTiles %>%
  addPolygons(
    # 폴리곤 내부
    fillColor = ~pal(당선), fillOpacity = 0.5,
    # 폴리곤 경계
    weight = 1, opacity = 1, color = "white", dashArray=3,
    # 라벨
    label=lapply(labs, htmltools::HTML),
    # 하이라이트
    highlightOptions = highlightOptions(
      color = "#00ff00", opacity = 1, weight = 2, fillOpacity = 1,
      bringToFront = T, sendToBack = T))%>%
  addLegend(pal = pal, values = ~당선, opacity = 0.7, title = NULL, position = "bottomright") %>%
  addPolylines(
    data=election_gu,
    weight = 1.5,
    opacity = 1,
    color = "black")

crosstalk::bscols(poly2)

단순히 생각해도, 투표에 영향을 주는 요소는 무수히 많습니다.

그렇다면 ‘과연 어떠한 요소가 실질적으로 투표에 영향을 줄까?’

이러한 의문으로 시작하여 저희 조는 투표에 영향을 줄 만한 변수들을 생각해봤고, 그 변수들을 이용하여 다음 총선을 예측해보기로 하였습니다.

1.2 데이터 수집과정

정량적인 데이터를 사용해야 하기 때문에, 선거에 통용되는 통설들은 배제하고 수치화 할 수 있는 데이터들을 수집했습니다.

library(tidyverse)
library(readr)
library(reticulate)
data<-read_csv(file="https://raw.githubusercontent.com/lhmlhm1111/Data_GongHak/master/2008_oldage.csv")

data %>%
  DT::datatable() %>%
  DT::formatRound(2:6, digits=0)

데이터수집예시

비슷한 과정으로 수치화 할 수 있는 데이터를 최대한 수집했습니다.

데이터수집목록

데이터수집목록

데이터 수집은 서울시열린데이터광장을 참고하였습니다. 서울시열린데이터광장

2 전처리과정

앞서 모은 데이터들을 활용하기 위해서 전처리 하는 과정을 거쳤습니다.

import pandas as pd
import numpy as np
import os
import re

gangnamgap = pd.read_excel("https://github.com/lhmlhm1111/Data_GongHak/raw/master/data/seoul/%EA%B0%9C%ED%91%9C%EC%83%81%ED%99%A9(%ED%88%AC%ED%91%9C%EA%B5%AC%EB%B3%84)_%EA%B0%95%EB%82%A8%EA%B5%AC%EA%B0%91.xlsx")
header = gangnamgap.iloc[2,:4]

a = pd.Series(gangnamgap.iloc[3,4:].values)

a = a.apply(lambda x: str(x).split("\n")[0])

a = a[(a!="")&(a!="nan")]

gangnamgap = gangnamgap[gangnamgap['Unnamed: 1']=="소계"]
gangnamgap = gangnamgap.iloc[:,:len(a)+3]
gangnamgap.columns = np.append(header,a[:-1])
gangnamgap.head()
##     읍면동명 투표구명   선거인수    투표수  새누리당 더불어민주당
## 9    신사동   소계  14827   7771  4774   2817
## 16  논현1동   소계  21876   8939  3966   4769
## 23  논현2동   소계  19063   8887  4639   4017
## 30  압구정동   소계  22435  12118  8301   3539
## 39   청담동   소계  24507  12470  7366   4777
os.chdir("C:/Users/JW/Desktop/presentation/data")
filelist = os.listdir("seoul")[1:]
first = gangnamgap
gangnamgap['자치구'] = "강남구"
for file in filelist:
    data=pd.read_excel(f'seoul/{file}')
    a=pd.Series(data.iloc[3,4:].values)
    a = a.apply(lambda x: str(x).split("\n")[0])
    a = a[(a!="")&(a!="nan")]
    data = data[data['Unnamed: 1']=="소계"]
    data = data.iloc[:,:len(a)+3]
    data.columns = np.append(header,a[:-1])
    gu = re.findall("_\w+구", file)[0][1:]
    data['자치구'] = gu
    first = first.append(data, sort=False)

Second = first[["읍면동명","자치구", "선거인수", "새누리당", "더불어민주당", "국민의당"]]
Second.읍면동명=Second.읍면동명.apply(lambda x: re.sub(r'제', '', str(x)))
## C:\ANACON~1\lib\site-packages\pandas\core\generic.py:4401: SettingWithCopyWarning: 
## A value is trying to be set on a copy of a slice from a DataFrame.
## Try using .loc[row_indexer,col_indexer] = value instead
## 
## See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
##   self[name] = value
Second.읍면동명=Second.읍면동명.apply(lambda x: re.sub(r'·', '.', str(x)))

old_man = pd.read_csv("https://github.com/lhmlhm1111/Data_GongHak/raw/master/data/%EB%8F%85%EB%A6%BD%EB%B3%80%EC%88%98_%EB%8D%B0%EC%9D%B4%ED%84%B0_%ED%98%B8%EC%8B%9D/%EC%84%9C%EC%9A%B8%EC%8B%9C%20%EB%8F%85%EA%B1%B0%EB%85%B8%EC%9D%B8%20%ED%98%84%ED%99%A9%20(%EC%84%B1%EB%B3%84%2C%EB%8F%99%EB%B3%84)%20%ED%86%B5%EA%B3%84_2016.txt", engine="python" ,encoding="utf-8", sep="\t")

old_man = old_man[["동", "자치구", "합계"]]
old_man=old_man.rename(columns={"동": "읍면동명"})
old_man = old_man.drop([0,1,2])

old_man.자치구=old_man.자치구.apply(lambda x: re.sub(r'성동', '중', str(x)))
old_man[old_man.자치구=="중구"]
##        읍면동명 자치구     합계
## 20       소계  중구  5,528
## 21      소공동  중구     54
## 22      회현동  중구    461
## 23       명동  중구    157
## 24       필동  중구    228
## 25      장충동  중구    187
## 26      광희동  중구    352
## 27     을지로동  중구    224
## 28     신당5동  중구    411
## 29      황학동  중구    514
## 30      중림동  중구    440
## 31      신당동  중구    385
## 32      다산동  중구    503
## 33      약수동  중구    755
## 34      청구동  중구    601
## 35      동화동  중구    256
## 53       소계  중구  9,025
## 54    왕십리2동  중구    546
## 55      마장동  중구    734
## 56      사근동  중구    338
## 57     행당1동  중구    511
## 58     행당2동  중구    616
## 59      응봉동  중구    423
## 60    금호1가동  중구    512
## 61    금호4가동  중구    478
## 62   성수1가1동  중구    452
## 63   성수1가2동  중구    442
## 64   성수2가1동  중구    677
## 65   성수2가3동  중구    335
## 66      송정동  중구    361
## 67      용답동  중구    665
## 68   왕십리도선동  중구    685
## 69  금호2.3가동  중구    654
## 70      옥수동  중구    596
second_old_man = pd.merge(Second, old_man, how='left')
second_old_man = second_old_man.rename(columns={"합계":"독거노인수"})

buyang = pd.read_csv("https://github.com/lhmlhm1111/Data_GongHak/raw/master/data/%EB%8F%85%EB%A6%BD%EB%B3%80%EC%88%98_%EB%8D%B0%EC%9D%B4%ED%84%B0_%ED%98%B8%EC%8B%9D/%EC%84%9C%EC%9A%B8%EC%8B%9C%20%EB%B6%80%EC%96%91%EB%B9%84%20%EB%B0%8F%20%EB%85%B8%EB%A0%B9%ED%99%94%EC%A7%80%EC%88%98%20(%EB%8F%99%EB%B3%84)%20%ED%86%B5%EA%B3%84_2016.txt", engine="python" ,encoding="utf-8", sep="\t")

buyang = buyang.rename(columns={"동":"읍면동명"})
buyang = buyang[~buyang.읍면동명.isin(["소계", "합계"])]
buyang=buyang.drop("기간", axis=1)

buyang.자치구=buyang.자치구.apply(lambda x: re.sub(r'성동', '중', str(x)))

old_man_buyang=pd.merge(second_old_man, buyang, how='left')
old_man_buyang.head()
##    읍면동명  자치구   선거인수  새누리당 더불어민주당 국민의당 독거노인수  유년부양비  노년부양비  노령화지수
## 0   신사동  강남구  14827  4774   2817  NaN   380   15.8   19.1  121.3
## 1  논현1동  강남구  21876  3966   4769  NaN   500    7.2   12.4  172.1
## 2  논현2동  강남구  19063  4639   4017  NaN   409   11.9   14.9  124.8
## 3  압구정동  강남구  22435  8301   3539  NaN   647   20.0   21.4  107.1
## 4   청담동  강남구  24507  7366   4777  NaN   491   16.3   15.2   93.5

비슷한 방식으로 다른 독립변수들도 모두 전처리를 해주었습니다.

여기까진 데이터를 단순히 전처리하는 과정이었습니다.

그 결과 결측치를 처리할 수 없었기 때문에, 아래와 같이 결측치를 처리해주었습니다.

import pandas as pd
election_2016=pd.read_csv("https://raw.githubusercontent.com/lhmlhm1111/Data_GongHak/master/%EC%A0%84%EC%B2%98%EB%A6%AC_1101(%EC%88%98%EC%A0%95).csv")
election_2016["독거노인수"]=election_2016["독거노인수"].apply(lambda x : int(str(x).replace(",", "")))
election_2016["기초수급자인원수"]=election_2016["기초수급자인원수"].apply(lambda x : int(str(x).replace(",", "")))
election_2016["사업체수"]=election_2016["사업체수"].apply(lambda x : int(str(x).replace(",", "")))
election_2016["종사자수"]=election_2016["종사자수"].apply(lambda x : int(str(x).replace(",", "")))
election_2016["금융기관"]=election_2016["금융기관"].fillna(election_2016['금융기관'].median())
election_2016["보육시설"]=election_2016["보육시설"].apply(lambda x : str(x))
election_2016["보육시설"]=election_2016["보육시설"].replace("nan", 0)
election_2016["보육시설"]=election_2016["보육시설"].apply(lambda x : int(str(x).replace(",", "")))
election_2016["보육시설"]=election_2016["보육시설"].replace(0, election_2016['보육시설'].median())
election_2016["사업체 평균연령"]=election_2016["사업체 평균연령"].fillna(election_2016['사업체 평균연령'].median())
election_2016["장애등급"]=election_2016["장애등급"].fillna(election_2016['장애등급'].median())
election_2016["국민의당"]=election_2016["국민의당"].fillna(0)
election_2016=election_2016.drop("Unnamed: 0", axis=1)
election_2016["새누리당"]=election_2016["새누리당"].fillna(0)
election_2016
##         읍면동명  자치구   선거인수     새누리당   ...      보육시설  금융기관  사업체 평균연령    장애등급
## 0        신사동  강남구  14827   4774.0   ...     303.0  13.0     6.833   383.0
## 1       논현1동  강남구  21876   3966.0   ...     375.0  18.0     7.250   648.0
## 2       논현2동  강남구  19063   4639.0   ...     287.0  23.0     7.583   509.0
## 3       압구정동  강남구  22435   8301.0   ...     301.0  32.0     7.167   471.0
## 4        청담동  강남구  24507   7366.0   ...     507.0  21.0     7.583   584.0
## 5       역삼1동  강남구  31222   5285.0   ...     767.0  54.0     6.917   760.0
## 6       역삼2동  강남구  26632   6988.0   ...     528.0  15.0     7.833   672.0
## 7       삼성1동  강남구  11991   3792.0   ...     565.0  29.0     7.667   281.0
## 8       삼성2동  강남구  23856   6262.0   ...     733.0  17.0     8.000   567.0
## 9       대치1동  강남구  16660   6362.0   ...     294.0  15.0     7.750   266.0
## 10      대치2동  강남구  31132  10404.0   ...     504.0  21.0     9.000   707.0
## 11      대치4동  강남구  16885   3467.0   ...     617.0  15.0     6.500   368.0
## 12      도곡1동  강남구  17461   5405.0   ...     412.0  11.0     8.083   431.0
## 13      도곡2동  강남구  26147   9715.0   ...     343.0  22.0     8.500   499.0
## 14      개포1동  강남구  17652   5341.0   ...     214.0   2.0    12.083   631.0
## 15      개포2동  강남구  19425   5321.0   ...     278.0   3.0    10.250   486.0
## 16      개포4동  강남구  16188   3656.0   ...     854.0   4.0     9.583   495.0
## 17      일원본동  강남구  18299   5411.0   ...     754.0   5.0    10.833   703.0
## 18      일원1동  강남구  14233   3527.0   ...     500.0   3.0    17.667  1045.0
## 19      일원2동  강남구  13325   3824.0   ...     479.0   3.0    11.334  1130.0
## 20       수서동  강남구  13814   4040.0   ...     560.0   4.0     9.750  2100.0
## 21       세곡동  강남구  31158   7100.0   ...    1619.0   1.0     8.083  2021.0
## 22       강일동  강동구  24321   5462.0   ...    1250.0   5.0     7.833  1558.0
## 23       상일동  강동구  16658   4424.0   ...     472.0   2.0    10.167   514.0
## 24      명일1동  강동구  18055   5328.0   ...     876.0   7.0     8.083   719.0
## 25      명일2동  강동구  14041   4576.0   ...     249.0   7.0     8.250   478.0
## 26      고덕1동  강동구  12181   3186.0   ...     607.0   4.0     9.500   547.0
## 27      고덕2동  강동구   7444   1775.0   ...     235.0   4.0    15.417   605.0
## 28      암사1동  강동구  29853   6142.0   ...    1461.0   3.0     8.334  1571.0
## 29      암사2동  강동구  12758   3003.0   ...     647.0   3.0     8.750   504.0
## ..       ...  ...    ...      ...   ...       ...   ...       ...     ...
## 394      광희동   중구   4332   1028.0   ...     219.0  16.0     9.583   251.0
## 395     을지로동   중구   1655    409.0   ...     131.0  11.0    12.833    99.0
## 396      신당동   중구   6765   1349.0   ...     163.0   7.0     5.833   377.0
## 397      다산동   중구  12804   2588.0   ...     309.0   4.0     9.167   670.0
## 398      약수동   중구  15496   3594.0   ...     514.0   2.0     9.334   888.0
## 399      청구동   중구  12568   2961.0   ...     264.0   1.0    10.334   658.0
## 400     신당5동   중구   8377   1578.0   ...     317.0   2.0     8.167   459.0
## 401      동화동   중구   9189   2166.0   ...     306.0   2.0     8.167   443.0
## 402      황학동   중구  10508   1950.0   ...     230.0   5.0    10.667   542.0
## 403      중림동   중구   7193   1581.0   ...     270.0   2.0    10.334   438.0
## 404    금호1가동   중구  10906   2394.0   ...     595.5   4.0    10.083   620.0
## 405  금호2.3가동   중구  18222   3741.0   ...     595.5   4.0    10.250   968.0
## 406    금호4가동   중구  11795   2378.0   ...     595.5   4.0    10.083   499.0
## 407      옥수동   중구  18401   4366.0   ...     595.5   4.0     8.500   680.0
## 408     면목본동  중랑구  30149   4798.0   ...     873.0   3.0     8.334  1646.0
## 409     면목2동  중랑구  22104   3516.0   ...     821.0   1.0     8.917  1279.0
## 410   면목3.8동  중랑구  23322   3836.0   ...     905.0   1.0     8.500  1272.0
## 411     면목4동  중랑구  18179   3085.0   ...     619.0   4.0     8.833  1271.0
## 412     면목5동  중랑구   9386   1434.0   ...     371.0   2.0     8.999   529.0
## 413     면목7동  중랑구  19706   3340.0   ...     638.0   2.0     9.000  1035.0
## 414     상봉2동  중랑구  16067   2542.0   ...     439.0   4.0     7.999   861.0
## 415     망우3동  중랑구  15293   2568.0   ...     604.0   1.0     8.667   957.0
## 416     상봉1동  중랑구  20177   4110.0   ...     656.0   4.0     8.917  1420.0
## 417     중화1동  중랑구  17246   3479.0   ...     645.0   1.0     9.083   861.0
## 418     중화2동  중랑구  24359   4508.0   ...     574.0   4.0     9.167  1510.0
## 419      묵1동  중랑구  27581   5769.0   ...    1051.0   3.0     8.667  1337.0
## 420      묵2동  중랑구  16180   3168.0   ...     517.0   2.0     9.917   869.0
## 421     망우본동  중랑구  27695   6104.0   ...     991.0   5.0    10.500  1722.0
## 422     신내1동  중랑구  31329   7003.0   ...    1514.0   2.0     9.250  1892.0
## 423     신내2동  중랑구  19790   4508.0   ...     748.0   3.0     9.167  1421.0
## 
## [424 rows x 19 columns]

최종적으로 전처리 한 데이터의 모습입니다.

data<-read_csv(file="https://raw.githubusercontent.com/lhmlhm1111/Data_GongHak/master/data/11-22totaldata.csv")

data %>%
  DT::datatable() %>%
  DT::formatRound(2:6, digits=0)

3 모델링

3.1 시작-데이터프레임불러오기

# 인코딩 문제를 해결하는 두가지 방법
## 1 csv파일 인코딩을 ANSI로 저장
df1=read.csv('https://github.com/lhmlhm1111/Data_GongHak/raw/master/%EC%A0%84%EC%B2%98%EB%A6%AC/%EC%86%8C%EB%93%9D%EB%B0%98%EC%98%81%EC%B5%9C%EC%A2%85.csv',header=T, sep=',')

## 2 readAny 패키지 활용

library (devtools)

# 패키지를 로드합니다.
library(readAny)
df2= read.any('https://github.com/lhmlhm1111/Data_GongHak/raw/master/%EC%A0%84%EC%B2%98%EB%A6%AC/%EC%86%8C%EB%93%9D%EB%B0%98%EC%98%81%EC%B5%9C%EC%A2%85.csv', header=T, sep=',')

3.2 데이터프레임 선형모델, 분산 분석, 각 독립변수 유의수준 유의성 검정

attach (df1)
names (df1)
##  [1] "year"                  "읍면동명"              "자치구"               
##  [4] "선거인수"              "새누리당"              "더불어민주당"         
##  [7] "국민의당"              "독거노인수"            "유년부양비"           
## [10] "노년부양비"            "노령화지수"            "사업체수"             
## [13] "종사자수"              "사업체.창업률"         "기초수급자인원수"     
## [16] "보육시설"              "금융기관"              "사업체.평균연령"      
## [19] "장애등급별.장애인현황" "인구"                  "면적"                 
## [22] "인구밀도"              "소득"
options("scipen" = 100)

model3 <- aov(새누리당~독거노인수+유년부양비+노년부양비+노령화지수+사업체수+종사자수+사업체.창업률+기초수급자인원수+보육시설+금융기관+사업체.평균연령+인구+면적+인구밀도+ 소득)
summary(model3)
##                   Df     Sum Sq   Mean Sq F value               Pr(>F)    
## 독거노인수         1  230185894 230185894 120.861 < 0.0000000000000002 ***
## 유년부양비         1  824836682 824836682 433.086 < 0.0000000000000002 ***
## 노년부양비         1  263678415 263678415 138.446 < 0.0000000000000002 ***
## 노령화지수         1    2339973   2339973   1.229             0.267997    
## 사업체수           1   93210115  93210115  48.941   0.0000000000054303 ***
## 종사자수           1    4871389   4871389   2.558             0.110135    
## 사업체.창업률      1     253293    253293   0.133             0.715442    
## 기초수급자인원수   1   47207560  47207560  24.787   0.0000007788404321 ***
## 보육시설           1   45819850  45819850  24.058   0.0000011246025274 ***
## 금융기관           1  111723182 111723182  58.661   0.0000000000000521 ***
## 사업체.평균연령    1     635956    635956   0.334             0.563521    
## 인구               1  721383036 721383036 378.767 < 0.0000000000000002 ***
## 면적               1   13405649  13405649   7.039             0.008129 ** 
## 인구밀도           1   33687732  33687732  17.688   0.0000288545948890 ***
## 소득               1   28932542  28932542  15.191             0.000105 ***
## Residuals        831 1582688042   1904558                                 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
  model4 <-lm(새누리당~독거노인수+유년부양비+노년부양비+노령화지수+사업체수+종사자수+사업체.창업률+기초수급자인원수+보육시설+금융기관+사업체.평균연령+인구+면적+인구밀도+ 소득)
summary(model4)
## 
## Call:
## lm(formula = 새누리당 ~ 독거노인수 + 유년부양비 + 노년부양비 + 
##     노령화지수 + 사업체수 + 종사자수 + 사업체.창업률 + 기초수급자인원수 + 
##     보육시설 + 금융기관 + 사업체.평균연령 + 인구 + 면적 + 인구밀도 + 
##     소득)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -9008.0  -433.0   148.9   695.5  4213.1 
## 
## Coefficients:
##                      Estimate   Std. Error t value             Pr(>|t|)    
## (Intercept)      869.28898889 717.55556041   1.211             0.226064    
## 독거노인수        -0.61702980   0.24730446  -2.495             0.012788 *  
## 유년부양비        35.02971651  21.72531987   1.612             0.107257    
## 노년부양비        37.69921285  26.50820910   1.422             0.155352    
## 노령화지수        -5.81151565   2.67440115  -2.173             0.030061 *  
## 사업체수          -0.02511495   0.05320288  -0.472             0.637008    
## 종사자수          -0.01857133   0.00798691  -2.325             0.020300 *  
## 사업체.창업률    -50.99068704  20.64504251  -2.470             0.013716 *  
## 기초수급자인원수   0.26304810   0.11784656   2.232             0.025873 *  
## 보육시설          -0.94835350   0.24324437  -3.899             0.000104 ***
## 금융기관          64.57554596  13.02162446   4.959          0.000000859 ***
## 사업체.평균연령   -2.69652286  38.11844206  -0.071             0.943621    
## 인구               0.19594165   0.01038664  18.865 < 0.0000000000000002 ***
## 면적             -29.26858362  42.14278105  -0.695             0.487557    
## 인구밀도          -0.02293503   0.00519833  -4.412          0.000011590 ***
## 소득               0.00023532   0.00006038   3.898             0.000105 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1380 on 831 degrees of freedom
## Multiple R-squared:  0.6048, Adjusted R-squared:  0.5977 
## F-statistic: 84.79 on 15 and 831 DF,  p-value: < 0.00000000000000022

3.3 변수 중요도 파악, 변수선택

library(reticulate)

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
#원본 데이터 호출 (깃허브에 저장된 데이터 파일 호출)
df4 = pd.read_csv('https://github.com/lhmlhm1111/Data_GongHak/raw/master/11-22totaldata.txt', encoding='utf-8', sep=',')

#train, test 데이터 생성
X, y = df4.iloc[:,8:], df4.iloc[:,4]


import warnings
warnings.filterwarnings("ignore")

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2, random_state=0)


## 랜덤포레스트 회귀 모델 생성&적용
rf = RandomForestRegressor()

rf.fit(X_train,y_train)
## RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,
##            max_features='auto', max_leaf_nodes=None,
##            min_impurity_decrease=0.0, min_impurity_split=None,
##            min_samples_leaf=1, min_samples_split=2,
##            min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,
##            oob_score=False, random_state=None, verbose=0, warm_start=False)
predicted = rf.predict(X_test)
rf.feature_importances_
## array([0.04645059, 0.02752551, 0.03782268, 0.01324745, 0.01213339,
##        0.01654494, 0.03641829, 0.04428583, 0.0226739 , 0.01858591,
##        0.03731588, 0.57759056, 0.03785546, 0.02623824, 0.04531137])
['{:f}'.format(x) for x in rf.feature_importances_]
## ['0.046451', '0.027526', '0.037823', '0.013247', '0.012133', '0.016545', '0.036418', '0.044286', '0.022674', '0.018586', '0.037316', '0.577591', '0.037855', '0.026238', '0.045311']
  • 상호관계 다중공선성
import PyQt5
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure


#가공할 데이터 호출
data = pd.read_csv('https://github.com/lhmlhm1111/Data_GongHak/raw/master/11-22totaldata.txt',encoding='UTF-8',sep=',')

#데이터 가공 : 변수 선별 (제외할 변수)
df3 = data.drop(['year','읍면동명','자치구','선거인수','인구'],axis=1)
#상관계수 분포 지도 (Heat Map) 작성
plt.rc('font', family='batang')

fig = plt.figure(figsize=[20,20])

ax=sns.heatmap(df3.corr(),annot=True,square=True)
plt.title('변수 간 상관관계')
plt.show()

최종적으로 소득 , 인구밀도 , 사업체수 , 장애등급별 장애인현황 ,독거노인수 , 노령화지수 선택

3.4 모델 선택 및 적용

모델 선택과정

최신 자료 예측 결과

4 결론

4.1 시각화

시각화

4.2 한계&제언 - 앞으로

변수변환, hyperparameter tuning 등의 미흡함.관측점 자체의 독립성? 앞으로 다음 학기 경선 후 후보자 발표되면 후보자의 관한 요인, 시국 여론 정보 (krvote 웹 크롤링부분 참고)추가, 그 이후 지역구 코드 활용해서 서울 이외의 지역까지 확장 가능?

import pandas as pd
import numpy as np

import seaborn as sns
import matplotlib.pyplot as plt
df1 = pd.read_csv('https://github.com/lhmlhm1111/Data_GongHak/raw/master/%EB%AA%A8%EB%8D%B8/12%2C16%EB%85%84%EB%8F%84_Training_Data_set_1.csv',encoding='UTF-8',sep=',')
x = '소득(동별)'
k=15
for i in range(k):
    df1.loc[(df1[x] >= (df1[x].max()-df1[x].min())/k*i ) & (df1[x] <= (df1[x].max()-df1[x].min())/k*(i+1) ) ,x] = i+1

plt.rc('font', family='Malgun Gothic')
fig = plt.figure(figsize=[16,16])
ax1 = fig.add_subplot(1,1,1)
ax1 = sns.barplot(x,y='새누리당',data=df1.groupby(x)['새누리당'].mean().reset_index())
plt.title('소득-새누리득표수')
plt.show()

5 질의