일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 박영선
- 데이터분석가채용
- 개발자취업
- 라이브코딩테스트
- 스타트업독서노트
- 데이터분석가
- 데이터과학자진로
- 데이터분석공부
- 데이터분석
- 데이터시각화
- 국민의힘경선
- 국회데이터시각화
- 안철수
- 로버트마틴
- 2021년회고
- 글또6기회고
- 신입개발자
- 데이터과학자의일
- 네이버트렌드
- 새파란
- 주니어개발자
- 회고
- 데이터분석가준비
- 2021년의 #봄여름가을겨울
- 360시간만에개발자되기
- 구글트렌드
- 360시간만에개발자
- 글또회고
- 서울시장
- 개발자면접
- Today
- Total
NEWBLUE's
[국회 데이터 시각화] plotly와 함께하는 대한민국 의회민주주의 발전사 - 어느 국회의원이 영향력이 있을까? 본문
[국회 데이터 시각화] plotly와 함께하는 대한민국 의회민주주의 발전사 - 어느 국회의원이 영향력이 있을까?
newblue 2020. 12. 20. 19:30본 게시물은 데이콘 대회에 제출하였던 코드를 기반으로 작성되었습니다 :)
안녕하세요. 새파란입니다.
데이터 시각화 공부도 할 겸 겸사겸사 위의 대회를 나가게 되었는데요.
평소에 matplotlib과 seaborn 만 써봤었는데, plotly가 깔끔해서 앞으로도 자주 이용할 것 같다는 생각이 드네요.
plotly 그래프를 티스토리에 올리기가 생각보다 쉽지 않은 것 같은데, 추가로 해당 내용들이 계속 변경될 수 있어 우선 이번 포스팅에서는 대회 및 플랫폼 소개와 그 전반적인 과정에 대해서 알아보도록 하겠습니다. 결과물은 본 포스팅 위와 아래에 있는 링크에서 확인하실 수 있습니다:)
(티스토리에도 jupyter notebook 플러그인이 있으면 좋을 것 같은데, 답답하면 제가 만들게 될지도 모르겠네요 )
1. 데이콘 소개
우선 데이터 관련 가장 유명한 플랫폼인 캐글이 대기업이라면, 데이콘은 약간 비슷한 길을 걷고자 하는 스타트업 느낌입니다.
항상 참가해야지 해야지 했다가 드디어 최근부터 참가를 시작하게 되었습니다. 이 전에 소설 작가 분류 AI 경진대회를 참여했었는데 (전에 관심이 없었던) NLP 관련 이론들에 대해 익숙해질 수 있는 좋은 계기였습니다.
2. 대회 소개
이번 대회의 목적은 (공지에서 참조했습니다.)
- 국회 활동이 쉽고 명확하게 보이도록 시각화
- 국회 활동에 대한 일반인의 관심을 제고할 수 있는 인사이트 발굴
이었습니다. 정당별 분류 혹은 인사이트는 많은 분들께서 해주시고 계신 것 같았기에, 저는 개개인의 국회의원을 조명하고 싶었습니다. 따라서 한때 유튜브에서 즐겨봤던 네고왕/발명왕 시리즈와 엮어서 국회 입법과 관련한 부문별로 '왕'을 뽑아보기로 했습니다.
1. 네트워크왕
2. 입안왕
3. 통과왕
4. ??왕 (업데이트예정)
3. 사용한 라이브러리 소개
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import networkx as nx
import plotly.io as pio
pio.renderers.default = "notebook_connected"
데이터 분석의 기본적인 pandas 라이브러리, 네트워크 분석시에 자주 사용하는 networkx 라이브러리, 그리고 위에서 언급했던 plotly 라이브러리를 사용했습니다.
plotly 라이브러리는 친해지는 중인데, (모든 기술이 다 그렇겠지만) 잘 쓸려면 시간이 조금 필요하겠네요.
plotly.graph_object 로 직접 설정을 해주기에는 번거로울 때가 많은데, plotly.express 를 이용하면 함수 하나로 그래프를 그릴 수 있습니다. 저도 많이 애용했습니다ㅎ.ㅎ
[결과물 미리보기]
(바로 이동하셔도 무방합니다.)
[국회 입법활동 빅데이터 시각화 경진대회]
우리나라 의회민주주의의 큰 축을 담당했던 인물은 누구일까요? 크게 4가지 측면에서 뽑아보았습니다. (혹시 더 좋은 조건이 생각나시면 댓글 주셔도 좋습니다.)
1. 네트워크왕
2. 입안왕
3. 통과왕
4. ??왕 (업데이트예정)
1. 네트워크왕 찾기
네트워크왕이란 국회의원들 사이에서 가장 영향력 있는 사람을 의미합니다. 법안 발의자-공동 발의자 관계로 법안을 제출해서 통과가 된 적이 있으면 그 횟수를 1로 셌습니다.
데이터 전처리
먼저 국회의원들의 의안 처리 결과가 나와있는 suggest 데이터를 활용합니다. 그 중에서 의안 처리 결과인 PROC_RESULT의 행을 관찰해봅시다.
suggest_raw = pd.read_csv("open/suggest.csv", encoding = "utf-8")
suggest_raw.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 62658 entries, 0 to 62657
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 BILL_ID 62658 non-null object
1 BILL_NO 62658 non-null int64
2 BILL_NAME 62658 non-null object
3 COMMITTEE 61821 non-null object
4 PROPOSE_DT 62651 non-null object
5 PROC_RESULT 58842 non-null object
6 AGE 62658 non-null int64
7 DETAIL_LINK 62658 non-null object
8 PROPOSER 62657 non-null object
9 MEMBER_LIST 62658 non-null object
10 RST_PROPOSER 62566 non-null object
11 PUBL_PROPOSER 59950 non-null object
dtypes: int64(2), object(10)
memory usage: 5.7+ MB
Null data 가 조금 있음을 알 수 있네요. 제거해서 자세히 데이터를 관찰해봅시다.
suggest_raw.dropna(axis=0).head(3)
BILL_ID | BILL_NO | BILL_NAME | COMMITTEE | PROPOSE_DT | PROC_RESULT | AGE | DETAIL_LINK | PROPOSER | MEMBER_LIST | RST_PROPOSER | PUBL_PROPOSER | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
557 | PRC_L2Y0T0X9V1K1V1Z5T3N3B2Q7D3Q2H3 | 2103783 | 119구조·구급에 관한 법률 일부개정법률안 | 행정안전위원회 | 2020-09-11 | 대안반영폐기 | 21 | http://likms.assembly.go.kr/bill/billDetail.do... | 서영교의원 등 11인 | http://likms.assembly.go.kr/bill/coactorListPo... | 서영교 | 강준현,김민철,김승원,박성준,송기헌,양정숙,윤미향,이상직,이성만,이수진 |
862 | PRC_X2Y0Y0M8A2E5P1R0P5S3J2Q4Z6T7I0 | 2103449 | 여권법 일부개정법률안 | 외교통일위원회 | 2020-09-02 | 철회 | 21 | http://likms.assembly.go.kr/bill/billDetail.do... | 최종윤의원등13인 | http://likms.assembly.go.kr/bill/coactorListPo... | 최종윤 | 기동민,김승남,박성준,서동용,양정숙,양향자,오영환,이용빈,이인영,인재근,조승래,허종식 |
881 | PRC_T2X0G0B9J0T2S1G0I2F2Q1P4G4O5O0 | 2103430 | 가정폭력범죄의 처벌 등에 관한 특례법 일부개정법률안 | 법제사법위원회 | 2020-09-02 | 대안반영폐기 | 21 | http://likms.assembly.go.kr/bill/billDetail.do... | 송기헌의원 등 10인 | http://likms.assembly.go.kr/bill/coactorListPo... | 송기헌 | 김남국,김민기,김성주,김승원,김종민,이광재,이탄희,조승래,황운하 |
'PROC_RESULT' 행이 아무래도 중요한 의미를 담고 있는 것 같아요. 자세히 살펴봅시다.
suggest_raw['PROC_RESULT'].value_counts()
임기만료폐기 34736
대안반영폐기 15479
수정가결 3189
폐기 2306
원안가결 1629
철회 1181
회기불계속폐기 228
수정안반영폐기 41
비상국무회의로이관 30
부결 23
Name: PROC_RESULT, dtype: int64
법안 통과를 i) '원안가결 + 수정가결', 또는 ii) '원안가결,수정가결,대안반영폐기'로 볼 수 있는데, 두 경우에 대해서 모두 데이터 프레임을 준비해둡시다.
suggest = suggest_raw[['AGE','PROC_RESULT','RST_PROPOSER','PUBL_PROPOSER']].dropna(axis=0)
suggest_approved_strong = suggest[(suggest['PROC_RESULT'] =='원안가결') | (suggest['PROC_RESULT'] =='수정가결')]
suggest_approved_weak = suggest[(suggest['PROC_RESULT'] =='원안가결') | (suggest['PROC_RESULT'] =='수정가결') | (suggest['PROC_RESULT'] =='대안반영폐기')]
먼저 dataframe이 주어지면 network를 만드는 함수, 그리고 그 결과 이미지를 반환하는 함수를 만들어봅시다. (보조 함수도 하나 만들었습니다.)
덧붙여 아래 참고문헌 [3] 에 논리를 참고해, 대표 발의에 비중을 두었습니다. 즉 A 국회의원이 B, C, D의원과 함께 법을 제출하면 관계가 A-B, A-C, A-D 이렇게 한 번만 생기게 됩니다.
def add_or_set(item,my_dict):
if item in my_dict:
my_dict[item] += 1
else:
my_dict[item] = 1
def make_network(dataframe):
edge = {}
node = {}
for idx,row in dataframe.iterrows():
proposer = row['RST_PROPOSER']
add_or_set(proposer,node)
if proposer in edge:
for publ_proposer in row['PUBL_PROPOSER'].split(","):
add_or_set(publ_proposer,edge[proposer])
add_or_set(publ_proposer,node)
else:
temp_dict = {}
for publ_proposer in row['PUBL_PROPOSER'].split(","):
temp_dict[publ_proposer] = 1
add_or_set(publ_proposer,node)
edge[proposer] = temp_dict
return node,edge
def draw_network(node,edge):
poli_graph = nx.Graph()
for congressman in node.keys():
poli_graph.add_node(congressman, size = node[congressman])
for proposer in edge.keys():
for publ_proposer in edge[proposer].keys():
poli_graph.add_edge(proposer,publ_proposer,weight = edge[proposer][publ_proposer])
pos_ = nx.spring_layout(poli_graph)
edge_x = []
edge_y = []
for edge in poli_graph.edges():
char_1 = edge[0]
char_2 = edge[1]
x0, y0 = pos_[char_1]
x1, y1 = pos_[char_2]
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None)
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
edge_trace = go.Scatter(
x=edge_x, y=edge_y,
line=dict(width=0.5, color='#888'),
hoverinfo='none',
mode='lines')
node_x = []
node_y = []
for node in poli_graph.nodes():
x, y = pos_[node]
node_x.append(x)
node_y.append(y)
node_trace = go.Scatter(
x=node_x, y=node_y,
mode='markers',
hoverinfo='text',
marker=dict(
showscale=True,
colorscale='YlGnBu',
reversescale=True,
color=[],
size=10,
colorbar=dict(
thickness=15,
title='누적 공동 발의자 수',
xanchor='left',
titleside='right'
),
line_width=2))
node_adjacencies = []
node_text = []
for node, adjacencies in enumerate(poli_graph.adjacency()):
node_adjacencies.append(len(adjacencies[1]))
node_text.append(str(adjacencies[0]) + '# of connections: '+str(len(adjacencies[1])))
node_trace.marker.color = node_adjacencies
node_trace.text = node_text
fig = go.Figure(data=[edge_trace, node_trace],
layout=go.Layout(
showlegend=False,
hovermode='closest',
margin=dict(b=20,l=5,r=5,t=40),
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
)
return fig
def show_network(dataframe,age):
node,edge = make_network(dataframe[dataframe['AGE']==age])
return draw_network(node,edge).show()
이렇게 함수로 만들고 나서, 네트워크 시각화를 하면 어떤 모습일까요?
대회 코드 공유 게시물 페이지에서 확인하실 수 있습니다 :)
(참고로 아직 대회가 끝나지 않아서, 계속 업데이트될 예정입니다)
'데이터 분석가가 되자, 지금 당장!' 카테고리의 다른 글
[보궐선거 결과 예측] 2021 서울시장 선거 승자 예측 - 구글 트렌드, 네이버 트렌드로 보는 선거 ver 3 (보너스 : 부산시장 승자 예측) (0) | 2021.04.06 |
---|---|
2021 서울 시장 보궐 선거 빅데이터 예측 - 구글 트렌드, 네이버 트렌드로 보는 선거 예측 ver 2 (보너스 : 부산시장 예측) (0) | 2021.03.07 |
2021 서울 시장 선거 데이터 분석 - 구글 트렌드, 네이버 트렌드로 보는 선거 예측 ver 1 (0) | 2021.02.06 |
[국회 데이터 시각화] 데이콘 데이터 시각화 대회 입상 후기 - 첫 데이터 대회 수상! (2) | 2021.01.12 |
[부동산 데이터 분석] 데린이의 서울 내 집 장만 프로젝트 (1) - pandas와 친해지기 (0) | 2020.11.27 |