https://petitions.assembly.go.kr/closed/agreeEnded
requests, bs4, pandas, time 불러오기
import time
from bs4 import BeautifulSoup as bs
import pandas as pd
import requests
page_no = 1
url = f'<https://petitions.assembly.go.kr/api/petits?pageIndex={page_no}&recordCountPerPage=8&sort=AGRE_END_DE-&searchCondition=sj&searchKeyword=&petitRealmCode=&sttusCode=PETIT_FORMATN,CMIT_FRWRD,PETIT_END&resultCode=BFE_OTHBC_WTHDRAW,PROGRS_WTHDRAW,PETIT_UNACPT,APPRVL_END_DSUSE,ETC_TRNSF¬InColumn=RESULT_CODE&beginDate=20180101&endDate=20230122&ageCd=>'
response = requests.get(url)
pd.read_json(url, encoding = 'utf-8').info() #98개의 칼럼이 있는 것을 확인
df = pd.read_json(url, encoding = 'utf-8').dropna(axis = 1)
df.info() #45개의 칼럼만 남은 것을 확인
df = df[['petitRealmNm','petitSj', 'resultCodeNm', 'agreBeginDe', 'agreEndDe', 'petitEndDt', 'agreCo', 'petitCn', 'petitId']]
- 칼럼 이름'petitSj' : 청원분야'agreBeginDe' : 동의 시작일'petitEndDt' : 청원 종료일'petitCn' : 청원 내용
- 'petitId' : id
- 'agreCo' : 동의수
- 'agreEndDe' : 동의 마감일
- 'resultCodeNm' : 청원결과
- 'petitRealmNm' : 제목
목록 수집 함수
def get_list(page_no) :
try :
url_list = f'<https://petitions.assembly.go.kr/api/petits?pageIndex={page_no}&recordCountPerPage=8&sort=AGRE_END_DE-&searchCondition=sj&searchKeyword=&petitRealmCode=&sttusCode=PETIT_FORMATN,CMIT_FRWRD,PETIT_END&resultCode=BFE_OTHBC_WTHDRAW,PROGRS_WTHDRAW,PETIT_UNACPT,APPRVL_END_DSUSE,ETC_TRNSF¬InColumn=RESULT_CODE&beginDate=20180101&endDate=20230122&ageCd=>'
df = pd.read_json(url_list, encoding = 'utf-8')
df = df[['petitRealmNm','petitSj', 'resultCodeNm','agreBeginDe', 'agreEndDe', 'petitEndDt', 'agreCo', 'petitCn', 'petitId']]
return df
except Exception as e :
print(f'이 {page_no}은 없는 페이지 입니다.{e}')
url 뒷부부분 beginDate=20180101&endDate=20230122&ageCd=> 여기가 날짜를 의미하는 것임
그냥 처음 들어갔을 때 그대로 하면 1년간의 데이터만 수집할 수 있어서 날짜를 맞추고 나서 url 을 긁어와야 함
마지막 페이지 까지 수집하는 함수
from tqdm import trange
import time
last_page = 79
page_list = []
for page_no in trange(1, last_page + 1) :
result = get_list(page_no)
page_list.append(result)
time. sleep(0.01)
# 모든 페이지 합치기
df = pd.concat(page_list)
ID를 가지고 청원 취지 가져오는 함수
def get_content(petit_id) :
try :
content_url = f'<https://petitions.assembly.go.kr/api/petits/{petit_id}?petitId={petit_id}&sttusCode=>'
response = requests.get(content_url)
cont = response.json()['petitObjet']
return cont
except Exception as e :
print(f'이 {petit_id}는 없는 아이디 입니다.{e}')
모두 적용하는 함수
# 모두 적용
from tqdm.notebook import tqdm
tqdm.pandas()
view = df['petitId'].progress_map(get_content)
view
df['petitObjet'] = view
저장
file_name = "국민동의청원수집.csv"
df.to_csv(file_name, index=False)
시각화 목적
- 사람들의 동의수를 많이 받은 청원분야는 무엇인가
- 연도별로 사람들의 많은 관심을 받은 청원 분야가 무엇이었는가
- 50,000 이상의 동의수를 얻어 성립된 청원들은 어떤 내용들로 구성되어 있는가
라이브러리 및 데이터 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.pyplot as plt
plt.rc('font', family='NanumBarunGothic') # 폰트 설정
plt.rc('axes', unicode_minus=False) # 마이너스 폰트 설정
%config InlineBackend.figure_format='retina' # 그래프 글씨 뚜렷
df = pd.read_csv('/content/drive/MyDrive/petitions.assembly.csv')
청원분야별 청원수
df[['청원 분야', '동의수']].groupby(df['청원 분야'], as_index = True).count()['청원 분야'].plot.bar(figsize = (12, 6))
청원 결과 한눈에 보기
pd.crosstab(df['청원 분야'], df['청원 결과'], margins = True).style.background_gradient(cmap='summer_r')
연도별 동의수가 많은 주제 알아보기
# 동의 시작 날짜 2020~2022
df_2022 = df[df['동의 시작 날짜'].str.contains('2022')]
df_2021 = df[df['동의 시작 날짜'].str.contains('2021')]
df_2020 = df[df['동의 시작 날짜'].str.contains('2020')]
agr2022 = df_2022[['청원 분야', '동의수']]
agr2022 = agr2022.groupby(agr2022['청원 분야'], as_index = True).sum()
agr2021 = df_2021[['청원 분야', '동의수']]
agr2021 = agr2021.groupby(agr2021['청원 분야'], as_index = True).sum()
agr2020 = df_2020[['청원 분야', '동의수']]
agr2020 = agr2020.groupby(agr2020['청원 분야'], as_index = True).sum()
data = pd.concat([agr2020, agr2021, agr2022], axis = 1)
data.columns = '2020', '2021', '2022'
# 연도별 동의수가 많은 카테고리
data.plot(kind = 'bar', figsize = (20, 10), title = '연도별', fontsize = 12)
plt.show()
- 사람들의 동의수를 많이 받은 청원분야는 무엇인가
- 연도별로 사람들의 많은 관심을 받은 청원 분야가 무엇이었는가
- 50,000 이상의 동의수를 얻어 성립된 청원들은 어떤 내용들로 구성되어 있는가
라이브러리 및 데이터 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.pyplot as plt
plt.rc('font', family='NanumBarunGothic') # 폰트 설정
plt.rc('axes', unicode_minus=False) # 마이너스 폰트 설정
%config InlineBackend.figure_format='retina' # 그래프 글씨 뚜렷
df = pd.read_csv('/content/drive/MyDrive/petitions.assembly.csv')
청원분야별 청원수
df[['청원 분야', '동의수']].groupby(df['청원 분야'], as_index = True).count()['청원 분야'].plot.bar(figsize = (12, 6))
청원 결과 한눈에 보기
pd.crosstab(df['청원 분야'], df['청원 결과'], margins = True).style.background_gradient(cmap='summer_r')
연도별 동의수가 많은 주제 알아보기
# 동의 시작 날짜 2020~2022
df_2022 = df[df['동의 시작 날짜'].str.contains('2022')]
df_2021 = df[df['동의 시작 날짜'].str.contains('2021')]
df_2020 = df[df['동의 시작 날짜'].str.contains('2020')]
agr2022 = df_2022[['청원 분야', '동의수']]
agr2022 = agr2022.groupby(agr2022['청원 분야'], as_index = True).sum()
agr2021 = df_2021[['청원 분야', '동의수']]
agr2021 = agr2021.groupby(agr2021['청원 분야'], as_index = True).sum()
agr2020 = df_2020[['청원 분야', '동의수']]
agr2020 = agr2020.groupby(agr2020['청원 분야'], as_index = True).sum()
data = pd.concat([agr2020, agr2021, agr2022], axis = 1)
data.columns = '2020', '2021', '2022'
# 연도별 동의수가 많은 카테고리
data.plot(kind = 'bar', figsize = (20, 10), title = '연도별', fontsize = 12)
plt.show()
- 사람들의 동의수를 많이 받은 청원분야는 무엇인가
- 연도별로 사람들의 많은 관심을 받은 청원 분야가 무엇이었는가
- 50,000 이상의 동의수를 얻어 성립된 청원들은 어떤 내용들로 구성되어 있는가
라이브러리 및 데이터 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.pyplot as plt
plt.rc('font', family='NanumBarunGothic') # 폰트 설정
plt.rc('axes', unicode_minus=False) # 마이너스 폰트 설정
%config InlineBackend.figure_format='retina' # 그래프 글씨 뚜렷
df = pd.read_csv('/content/drive/MyDrive/petitions.assembly.csv')
청원분야별 청원수
df[['청원 분야', '동의수']].groupby(df['청원 분야'], as_index = True).count()['청원 분야'].plot.bar(figsize = (12, 6))
청원결과 한눈에 보기
pd.crosstab(df['청원 분야'], df['청원 결과'], margins = True).style.background_gradient(cmap='summer_r')
연도별 동의수가 많은 주제 알아보기
# 동의 시작 날짜 2020~2022
df_2022 = df[df['동의 시작 날짜'].str.contains('2022')]
df_2021 = df[df['동의 시작 날짜'].str.contains('2021')]
df_2020 = df[df['동의 시작 날짜'].str.contains('2020')]
agr2022 = df_2022[['청원 분야', '동의수']]
agr2022 = agr2022.groupby(agr2022['청원 분야'], as_index = True).sum()
agr2021 = df_2021[['청원 분야', '동의수']]
agr2021 = agr2021.groupby(agr2021['청원 분야'], as_index = True).sum()
agr2020 = df_2020[['청원 분야', '동의수']]
agr2020 = agr2020.groupby(agr2020['청원 분야'], as_index = True).sum()
data = pd.concat([agr2020, agr2021, agr2022], axis = 1)
data.columns = '2020', '2021', '2022'
# 연도별 동의수가 많은 카테고리
data.plot(kind = 'bar', figsize = (20, 10), title = '연도별', fontsize = 12)
plt.show()
워드클라우드
목적
- 사람들의 동의수를 많이 받은 청원분야는 무엇인가
- 연도별로 사람들의 많은 관심을 받은 청원 분야가 무엇이었는가
- 50,000 이상의 동의수를 얻어 성립된 청원들은 어떤 내용들로 구성되어 있는가
라이브러리 및 데이터 불러오기
!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf #colab 사용
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.pyplot as plt
plt.rc('font', family='NanumBarunGothic') # 폰트 설정
plt.rc('axes', unicode_minus=False) # 마이너스 폰트 설정
%config InlineBackend.figure_format='retina' # 그래프 글씨 뚜렷
df = pd.read_csv('/content/drive/MyDrive/petitions.assembly.csv')
연도별 성립된 청원 데이터 정리
agr = df[df['청원 결과'] != '동의만료폐기']
# 동의 시작 날짜가 object고 날짜 데이터가 따로 필요하지 않아서 str.contains로 찾았습니다
pass_2022 = agr[agr['동의 시작 날짜']. str.contains('2022')].reset_index(drop = True)
pass_2021 = agr[agr['동의 시작 날짜']. str.contains('2021')].reset_index(drop = True)
pass_2020 = agr[agr['동의 시작 날짜']. str.contains('2020')].reset_index(drop = True)
pass_2022.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 8 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 청원 분야 24 non-null object
1 청원 주제 24 non-null object
2 청원 취지 24 non-null object
3 청원 결과 24 non-null object
4 동의수 24 non-null int64
5 청원 내용 24 non-null object
6 동의 시작 날짜 24 non-null object
7 동의 종료 날짜 24 non-null object
dtypes: int64(1), object(7)
memory usage: 1.6+ KB
데이터를 확인해 보니 양이 많지 않아 내용을 word cloud 사용하여 정리하기로 함
텍스트만 뽑기
content_22 = ''
for i in range(len(pass_22['청원 내용'])) :
content_22 = content_22 + ' ' + pass_22['청원 내용'].loc[i]
content_21 = ''
for i in range(len(pass_21['청원 내용'])) :
content_21 = content_21 + ' ' + pass_21['청원 내용'].loc[i]
content_20 = ''
for i in range(len(pass_20['청원 내용'])) :
content_20 = content_20 + ' ' + pass_20['청원 내용'].loc[i]
단어 전처리
import re
content_20 = re.sub("[^가-힣ㄱ-ㅎㅏ-ㅣ]", " ", content_20)
content_21 = re.sub("[^가-힣ㄱ-ㅎㅏ-ㅣ]", " ", content_21)
content_22 = re.sub("[^가-힣ㄱ-ㅎㅏ-ㅣ]", " ", content_22)
!pip install matplotlib-venn
!apt-get -qq install -y libfluidsynth1
!curl -s <https://raw.githubusercontent.com/teddylee777/machine-learning/master/99-Misc/01-Colab/mecab-colab.sh> | bash
# colab에서 konlpy 쓰기 위해
!pip install customized_konlpy # colab에서 Tiwtter 쓰기 위해
from konlpy.tag import Okt
okt = Okt()
nouns20_txt = okt.nouns(content_20)
nouns20_txt
from ckonlpy.tag import Twitter # 기존의 단어 품사 바꾸는 건 안 됨
Twitter = Twitter()
Twitter.add_dictionary('낙태허용', 'Noun')
Twitter.add_dictionary('낙태 허용', 'Noun')
Twitter.add_dictionary('심장박동', 'Noun')
Twitter.add_dictionary('심장 박동', 'Noun')
Twitter.add_dictionary('약물처방', 'Noun')
Twitter.add_dictionary('약물 처방', 'Noun')
Twitter.add_dictionary('계획안', 'Noun')
Twitter.add_dictionary('계획 안', 'Noun')
Twitter.add_dictionary('대통령 특별 담화 요구', 'Noun')
Twitter.add_dictionary('대통령특별담화요구', 'Noun')
Twitter.add_dictionary('초 중등교육', 'Noun')
Twitter.add_dictionary('초중등교육육', 'Noun')
Twitter.add_dictionary('교육기관', 'Noun')
Twitter.add_dictionary('교육 기관', 'Noun')
Twitter.add_dictionary('불법낙태', 'Noun')
Twitter.add_dictionary('불법 낙태', 'Noun')
Twitter.add_dictionary('약 처방', 'Noun')
Twitter.add_dictionary('약처방', 'Noun')
Twitter.add_dictionary('임신중단', 'Noun')
Twitter.add_dictionary('임신 중단', 'Noun')
Twitter.add_dictionary('임신중단시술', 'Noun')
Twitter.add_dictionary('임신 중단 시술술', 'Noun')
Twitter.add_dictionary("n번방", "Noun")
Twitter.add_dictionary("n 번방", "Noun")
Twitter.add_dictionary("텔레그램", "Noun")
Twitter.add_dictionary("텔레 그램", "Noun")
Twitter.add_dictionary("법 개정", "Noun")
Twitter.add_dictionary("생계 보호", "Noun")
Twitter.add_dictionary("생계보호호", "Noun")
Twitter.add_dictionary("사업추진", "Noun")
Twitter.add_dictionary("사업 추진진", "Noun")
Twitter.add_dictionary("근로제한", "Noun")
Twitter.add_dictionary("근로 제한한", "Noun")
Twitter.add_dictionary("국가 지자체", "Noun")
Twitter.add_dictionary("국가지자체체", "Noun")
Twitter.add_dictionary("계약 체결", "Noun")
Twitter.add_dictionary("계약체결결", "Noun")
Twitter.add_dictionary("법률 개정안", "Noun")
Twitter.add_dictionary("법률개정안", "Noun")
okt = Okt()
nouns20_txt = okt.nouns(content_20)
nouns21_txt = okt.nouns(content_21)
nouns22_txt = okt.nouns(content_22)
워드클라우드 라이브러리 불러오기
!pip install wordcloud
from wordcloud import WordCloud
from PIL import Image
!apt-get update -qq
!apt-get install fonts-nanum* -qq
!pip install matplotlib-venn
!apt-get -qq install -y libfluidsynth1
import matplotlib.font_manager as fm
sys_font = fm.findSystemFonts()
[f for f in sys_font if 'Nanum' in f]
img_path = '/content/drive/MyDrive/images_bluespot9_post_cd03caf8-d809-4b9f-b4d2-7a932e696932_cloud.png'
2020년 워드클라우드
from collections import Counter
count20 = Counter(nouns20_txt)
count20
rank_text20 = count20.most_common()
rank_text20 = dict(rank_text20)
count20_len = 4 #4번 미만 나온 단어들은 빼기기
temp_dic20 = {}
for key, value in rank_text20.items():
if value > count20_len:
temp_dic20[key] = value
rank_text20 = temp_dic20
[rank_text20.pop(key) for key in ['법', '수', '등', '것', '제', '대한', '의사', '조', '년', '이',
'일', '명', '위', '그', '위해', '및', '월', '정', '자', '관', '만', '의',
'중', '로', '전', '초']]
import wordcloud
flower_mask = np.array(Image.open(img_path))
wordcloud = WordCloud(font_path = '/usr/share/fonts/truetype/nanum/NanumGothic.ttf',
background_color = 'white', mask = flower_mask)
wc = wordcloud.generate_from_frequencies(rank_text20)
plt.figure(figsize = (8,15))
plt.imshow(wc)
plt.imshow(wc, interpolation= 'bilinear')
plt.axis('off')
plt.show()
2021년 워드 클라우드
nouns21_txt = okt.nouns(content_21)
nouns21_txt
okt = Okt()
nouns21_txt = okt.nouns(content_21)
nouns21_txt
from collections import Counter
count21 = Counter(nouns21_txt)
count21
rank_text21 = count21.most_common()
rank_text21
rank_text21 = dict(rank_text21)
count21_len = 4
temp_dic21 = {}
for key, value in rank_text21.items():
if value > count21_len:
temp_dic21[key] = value
rank_text21 = temp_dic21
[rank_text21.pop(key) for key in ['것', '수', '등', '법', '년', '제', '위', '이', '및', '말', '위해', '명', '의',
'저', '그', '함', '만', '전', '조', '중']]
import wordcloud
flower_mask = np.array(Image.open(img_path))
wordcloud = WordCloud(font_path = '/usr/share/fonts/truetype/nanum/NanumGothic.ttf',
background_color = 'white', mask = flower_mask)
wc = wordcloud.generate_from_frequencies(rank_text21)
plt.figure(figsize = (8,15))
plt.imshow(wc)
plt.imshow(wc, interpolation= 'bilinear')
plt.axis('off')
plt.show()
2022년 워드 클라우드
nouns22_txt = okt.nouns(content_22)
nouns22_txt
okt = Okt()
nouns22_txt = okt.nouns(content_22)
nouns22_txt
from collections import Counter
count22 = Counter(nouns22_txt)
count22
rank_text22 = count22.most_common()
rank_text22
rank_text22 = dict(rank_text22)
count22_len = 4
temp_dic22 = {}
for key, value in rank_text22.items():
if value > count22_len:
temp_dic22[key] = value
rank_text22 = temp_dic22
rank_text22
[rank_text22.pop(key) for key in ['것', '수', '년', '등', '제', '법', '기관', '이', '위', '조', '일', '및', '월',
'그', '회', '위해', '또한', '안', '명', '해당', '때문', '대해', '함', '모든',
'때', '더', '항', '전', '투', '중', '사항', '뿐', '정', '다른', '내']]
import wordcloud
flower_mask = np.array(Image.open(img_path))
wordcloud = WordCloud(font_path = '/usr/share/fonts/truetype/nanum/NanumGothic.ttf',
background_color = 'white', mask = flower_mask)
wc = wordcloud.generate_from_frequencies(rank_text22)
plt.figure(figsize = (8,15))
plt.imshow(wc)
plt.imshow(wc, interpolation= 'bilinear')
plt.axis('off')
plt.show()
- 좋았던 것(Liked) : 새로운 라이브러리를 사용해봤다. (word cloud) / 강사님 도움 없이 처음으로 한 제이터
- 배운 것(Learned) : 일단 해보자라는 마음을 배운 것 같다. 그 전까지만 해도 안 배운 부분을 어떻게 혼자하지 라는 생각을 했는데 구글링해서 찾아본 것을 바탕으로 일단 해보면 완성하지는 못하더라도 그 과정을 알아가며 성장할 수 있었다.
- 부족했던 것(Lacked) : 시각화 실력. matplolib 과 seaborn을 아주 조금 다룰 수 있어서 그걸 바탕으로 그래프를 만들다보니 한계가 있었다. 그리고 수박 겉핥기식 배움이라 한 번 각 잡고 기초부터 다져야겠다.
- 바라는 것(Longed for) : 노력
'AI SCHOOL > project' 카테고리의 다른 글
[mini project 2] 공공데이터를 활용한 대한민국 산업재해 현황 분석 (0) | 2023.02.05 |
---|---|
[mini project] 스타벅스 매장정보 수집 (0) | 2023.01.29 |