반응형

안녕하세요! ㅎㅎ

오늘은 folium을 이용해서 지리정보 시각화를 간단히 해 보려고 합니다.

그럼 시작하겠습니다!

Preview

step1. 데이터 준비하기

오늘 사용할 데이터는 서울 열린 데이터 광장의 '용산구 cctv 설치현황. csv'를 다운로드하여 시각화할 예정입니다.

아래의 링크를 눌러 csv파일을 다운로드 받아 주세요.

[서울 용산구 cctv] 설치현황

 

열린데이터광장 메인

데이터분류,데이터검색,데이터활용

data.seoul.go.kr

위의 내려받기(CSV)를 클릭하면 csv파일이 다운받아집니다:)

 

step 2. 위치정보 데이터 추출하기

위에서 다운로드하여준 csv를 열어 주고 내용을 확인해 보도록 하겠습니다.

항상 파일 위치를 열 때는 \를 //로 바꿔주어야 유니코드 오류가 뜨지 않고 잘 열 수 있습니다.

# CSV 파일 열기
import pandas as pd
file = r'C:\파일위치\yongsan_CCTV.csv'
file = file.replace('\\','//')
#print(file)
cctv_csv = pd.read_csv(file,encoding='cp949')
print(cctv_csv.head(5))

출력:

이렇게 용산구의 cctv가 있는 주소, x, y좌표 등등의 정보를 확인할 수 있습니다.

파일 중간중간 NAN이 있는 걸로 보아 위치 데이터에도 값이 없는 부분이 있을 수 있어

NaN이 있는 부분을 전부 0으로 바꾸어 주도록 하겠습니다.

# 데이터프레임 NaN 값 대체
cctv_csv = cctv_csv.fillna(0.0)
print(cctv_csv.head())

출력:

위처럼 NaN이 0.0으로 모두 바뀌었습니다.

이제 위치를 지도에 표시하기 위해 x좌표(위도), y좌표(경도)를 따로 준비해 주도록 하겠습니다.

여기서 0.0 값(NaN값이었던)을 가지는 행은 제외하고 좌표를 리스트로 모아보도록 하겠습니다. 

# x좌표(위도),y좌표(경도) 리스트로 만들기
x = []
y = []
for i in range(len(cctv_csv['WGS x좌표'])):
    if cctv_csv['WGS x좌표'][i] == 0.0 or cctv_csv['WGS y좌표'][i] == 0.0:
        pass
    else:

        x.append(cctv_csv['WGS x좌표'][i])
        y.append(cctv_csv['WGS y좌표'][i])
print('x갯수: ',len(x))
print('y갯수: ',len(y))

출력:

이렇게 위, 경도 각각 743개가 잘 들어가 있음을 확인할 수 있습니다.

 

step3. 지도에 위치 마커 표시하기

이제 folium을 이용해 지도를 불러오고, 불러온 지도에 CCTV 위치 정보를 표시하여 시각화해보도록 하겠습니다.

#지도 생성 및 marker 지정하기
import folium
map_osm = folium.Map(location=[x[13],y[13]],zoom_start=14)
for i in range(len(x)):
    folium.Marker([x[i],y[i]], popup='용산CCTV_%d'%i, icon=folium.Icon(color='red', icon='info-sign')).add_to(map_osm)
# 지도에서 범위 지정
folium.CircleMarker(location=[x[13],y[13]],popup='용산구 CCTV', radius=300, color="#3186cc", fill_color="#3186cc").add_to(map_osm)
#map저장
map_osm.save('yongsan_cctv.html')

출력:

위와 같이 Marker를 지정하면 아이콘 모양 및 색상을 정할 수 있습니다. pop-up은 지도에 표시되어 있는 아이콘을 클릭했을 때 나오는 설명 문구입니다. 

여기에서는 csv의 cctv입력 순서에 따라 cctv_1 cctv_2 cctv3... 등으로 이름을 지정해 주었습니다.

또 서클 마커(CircleMarker)를 사용하면 위의 파란색 원과 같이 범위를 지정할 수 있습니다.

색 또한 지정 가능하니 참고하시면 됩니다.

전체 코드
# CSV 파일 열기
import pandas as pd
file = r'파일위치\yongsan_CCTV.csv'
file = file.replace('\\','//')
#print(file)
cctv_csv = pd.read_csv(file,encoding='cp949')
print(cctv_csv.head(5))

# 데이터프레임 NaN 값 대체
cctv_csv = cctv_csv.fillna(0.0)
print(cctv_csv.head())

# x좌표(위도),y좌표(경도) 리스트로 만들기
x = []
y = []
for i in range(len(cctv_csv['WGS x좌표'])):
    if cctv_csv['WGS x좌표'][i] == 0.0 or cctv_csv['WGS y좌표'][i] == 0.0:
        pass
    else:

        x.append(cctv_csv['WGS x좌표'][i])
        y.append(cctv_csv['WGS y좌표'][i])
print('x갯수: ',len(x))
print('y갯수: ',len(y))



#지도 생성 및 marker 지정하기
import folium
map_osm = folium.Map(location=[x[13],y[13]],zoom_start=14)
for i in range(len(x)):
    folium.Marker([x[i],y[i]], popup='용산CCTV_%d'%i, icon=folium.Icon(color='red', icon='info-sign')).add_to(map_osm)
# 지도에서 범위 지정
folium.CircleMarker(location=[x[13],y[13]],popup='용산구 CCTV', radius=300, color="#3186cc", fill_color="#3186cc").add_to(map_osm)
#map저장
map_osm.save('yongsan_cctv.html')

 

코드 파일

cctv_map.py
0.00MB

참고 문서

folium 공식문서

 

Folium — Folium 0.12.1 documentation

folium builds on the data wrangling strengths of the Python ecosystem and the mapping strengths of the leaflet.js library. Manipulate your data in Python, then visualize it in on a Leaflet map via folium. Concepts folium makes it easy to visualize data tha

python-visualization.github.io

마무리

 

오늘은 파이썬으로 지도위치 시각화하는 방법을 알아보았습니다ㅎㅎ csv파일과 위치 좌표만 있으면

간편하게 시각화가 가능합니다. 질문은 댓글 달아주세요 :)

반응형
반응형

안녕하세요!

오늘은 저번에 만들었던 네이버 블로그 크롤러를 이용해서 txt 파일을 만들고

만들어진 텍스트 파일을 이용하여 워드 클라우드(WordCloud)로 시각화해보도록 하겠습니다.

 

step1. 데이터 준비
 

[python] Naver 오픈API를 이용하여 원하는 검색어로 블로그 크롤링 하기(제목+본문)

오늘은 NAVER API를 이용하여 네이버 블로그 크롤링을 해 보겠습니다 ;) NAVER OPEN API 신청하는 방법은 여기를 클릭해주세요ㅎㅎ step1. 네이버 OPEN API를 이용하여 원하는 검색어로 관련 게시물 불러오

wonhwa.tistory.com

 

위의 링크를 클릭하여 원하는 검색어 입력 후 관련 내용을 text 파일로 만들어 준비해 줍니다.

저는 '상암 맛집' 이라는 키워드로 'blog_text.txt' 파일을 만들어 보았습니다.

blog_text.txt
0.42MB

 

이제 위 파일 또는 다른 검색어로 크롤링한 파일을 파이썬으로 열어 줍니다.

파이썬으로 파일 주소를 입력할 때는 꼭 \를 //로 바꾸어 주세요!

# text 파일 읽어오기
#※※주소불러올때 \를 //로 바꾸어주기※※
blog_text = open('주소입력//blog_text.txt','rt', encoding='UTF-8').read()

# csv 파일일때
# import pandas as pd
# blog_text = pd.read_csv('csv파일.csv',encoding='utf-8')
# blog_text = blog_text['형태소분석할 컬럼명']
step2. Konlpy를 이용해 text의 형태소 분석하여 텍스트 전처리하기

텍스트 파일을 불러오고, 파일 안에 텍스트들을 konlpy를 이용해 명사, 형용사만 추출하도록 하겠습니다.

konlpy의 Okt를 이용하여 추출하도록 하겠습니다.

텍스트 한 줄 마다 형용사와 명사를 뽑아

n_adj라는 변수에 리스트를 만들어 단어를 추가해 줍니다.

from konlpy.tag import Okt
from collections import Counter

# Okt 함수를 이용해 형태소 분석
okt = Okt()
line =[]

line = okt.pos(blog_text)

n_adj =[]
# 명사 또는 형용사인 단어만 n_adj에 넣어주기
for word, tag in line:
    if tag in ['Noun','Adjective']:
        n_adj.append(word)
# 명사 또는 형용사인 단어 및 2글자 이상인 단어 선택 시
# n_adj = [word for word, tag in line if tag in ['Noun','Adjective'] and len(word) > 1]
print(n_adj)

출력:

위에를 보면 '아니었네요. ,  끝' 등과 같은 워드클라우드를 만들 때 부적절한 단어가 있습니다.

위같은 단어를 '불용어(stopwords)'라고 하는데 이 불용어들을 리스트에서 지워 주도록 하겠습니다.

#제외할 단어 추가
stop_words = "아니었네요. 있어서 끝 " #추가할 때 띄어쓰기로 추가해주기
stop_words = set(stop_words.split(' '))
# 불용어를 제외한 단어만 남기기
n_adj = [word for word in n_adj if not word in stop_words]

다음으로 같은 단어들이 2개 이상 나오는 것들을 counter를 이용하여 세어 주고,

가장 많이 나온 단어 100단어만 남기겠습니다.

#가장 많이 나온 단어 100개 저장
counts = Counter(n_adj)
tags = counts.most_common(100)

그 후 이 100단어들로 워드클라우드를 만들어 보겠습니다.

step3. 워드클라우드 만들기

저는 워드 클라우드에 모양을 넣어주고 싶어 하트 모양의 사진을 준비하여

하트 모양의 워드 클라우드를 만들어 보았습니다.

이런 하트 사진 또는 원하는 사진을 (배경이 투명해야 합니다.) 다운로드 받아 주세요.

# 이미지 추가(워드크라우드 모양 설정)
import numpy as np
from PIL import Image

mask = Image.new("RGBA",(2555,2275), (255,255,255)) #(2555,2575)는 사진 크기, (255,255,255)는 색을의미
image = Image.open('사진주소//heart.png').convert("RGBA")
x,y = image.size
mask.paste(image,(0,0,x,y),image)
mask = np.array(mask)

이렇게 이미지를 설정해주고,(제가 사용하는 이미지는 2555 x 2275 pixel 입니다.)

위의 mask를 사용하여 WordCloud를 만들어 주도록 하겠습니다.

한글을 사용하기 때문에 원하는 폰트 파일(.ttf)을 다운받아 설치하여 아래와 같이 파일 위치 및 이름을 적어줍니다.

저는 배경은(background) 검은색(black)으로, mask(모양)은 하트모양으로, 색상(colormap)은 프리즘(prism)을 이용해 

워드 클라우드를 만들어 주었습니다.

from wordcloud import WordCloud

###WordCloud(워드크라우드) 만들기###
#폰트지정
font='C://Users//user//AppData//Local//Microsoft//Windows//Fonts//BMDOHYEON.ttf'
word_cloud = WordCloud(font_path=font, background_color='black',max_font_size=400, mask=mask,colormap='prism').generate_from_frequencies(dict(tags))

# 사이즈 설정 및 화면에 출력
import matplotlib.pyplot as plt
plt.figure(figsize=(10,8))
plt.imshow(word_cloud)
plt.axis('off')
#워드클라우드 사진으로 저장
#cloud.to_file('상암맛집_wc.png')
#또는
plt.savefig('상암맛집.png', bbox_inches='tight')
plt.show()

출력:

그럼 위에 모양과 같이 하트모양의 상암맛집과 관련한 워드클라우드가 만들어졌습니다. ㅎㅎ

저는 검색어를 상암맛집으로 했기 때문에 이를 보여주기 위해 상암 맛집을 그대로 놔두었지만,

상암 맛집을 검색해서 나온 내용을 텍스트로 만들었기때문에 실제 정확한 분석을 위해서는

'상암, 맛집' 이 두 단어를 불용어로 두어 처리하고 다른 불용어를 더 추가해 다듬는다면

더 퀄리티 높은 워드클라우드가 만들어질 것 같습니다.

 

++추가로 워드클라우드의 글자 색상은 워드클라우드 파라미터인 colormap을 통해 변경할 수 있습니다.

아래 사진을 참고하여 원하는 컬러 맵 이름을 파라미터에 적어주면 적용 됩니다 :)

ex) colormap = 'autumn' 이런 식으로 작성하면 됩니다.

참고해 주세요 ^0^

컬러맵 종류

전체 코드
from konlpy.tag import Okt
from wordcloud import WordCloud
from collections import Counter

# text 파일 읽어오기
#※※주소불러올때 \를 //로 바꾸어주기※※
blog_text = open('C://주소//blog_text.txt','rt', encoding='UTF-8').read()
#print(blog_text)

# csv 파일일때
# import pandas as pd
# blog_text = pd.read_csv('csv파일.csv',encoding='utf-8')
# blog_text = blog_text['형태소분석할 컬럼명']

# Okt 함수를 이용해 형태소 분석
okt = Okt()
line =[]

line = okt.pos(blog_text)

n_adj =[]
# 명사 또는 형용사인 단어만 n_adj에 넣어주기
for word, tag in line:
    if tag in ['Noun','Adjective']:
        n_adj.append(word)
# 명사 또는 형용사인 단어 및 2글자 이상인 단어 선택 시
# n_adj = [word for word, tag in line if tag in ['Noun','Adjective'] and len(word) > 1]

#제외할 단어 추가
stop_words = "상암맛집 입니다 있어서 입니다." #추가할 때 띄어쓰기로 추가해주기
stop_words = set(stop_words.split(' '))

n_adj = [word for word in n_adj if not word in stop_words]
print(n_adj)

#print(line)
#print(n_adj)

#가장 많이 나온 단어 100개 저장
counts = Counter(n_adj)
tags = counts.most_common(100)

# 이미지 추가(워드크라우드 모양 설정)
import numpy as np
from PIL import Image

mask = Image.new("RGBA",(2555,2275), (255,255,255)) #(2555,2575)는 사진 크기, (255,255,255)는 색을의미
image = Image.open('C://Users//user//주소//heart.png').convert("RGBA")
x,y = image.size
mask.paste(image,(0,0,x,y),image)
mask = np.array(mask)

###WordCloud(워드크라우드) 만들기###
#폰트지정
font='C://폰트주소//폰트이름.ttf'
word_cloud = WordCloud(font_path=font, background_color='black',max_font_size=400, mask=mask,colormap='prism').generate_from_frequencies(dict(tags))

# 사이즈 설정 및 화면에 출력
import matplotlib.pyplot as plt
plt.figure(figsize=(10,8))
plt.imshow(word_cloud)
plt.axis('off')
#워드클라우드 사진으로 저장
#cloud.to_file('상암맛집_wc.png')
#또는
plt.savefig('상암맛집.png', bbox_inches='tight')
plt.show()

 

코드 파일

word_cloud_blog.py
0.00MB

마무리

오늘은 크롤링한 텍스트파일로 워드클라우드를 만들어 보았습니다.

항상 전처리가 시간이 많이 걸리고 전처리를 잘 해야 시각화도 잘 되어서 그 중요성을 다시 깨닫게 되네요ㅎㅎ

이번에는 블로그를 예제로 해서 워드클라우드를 만들었지만

뉴스나 연설문 등을 텍스트로 만들어 워드클라우드 해봐도 좋겠네요.

더 궁금한 것이 있다면 댓글 남겨주세요 :)

반응형
반응형

최근에 konlpy.tag를 사용하는 도중

Exception has occurred: SystemError
java.nio.file.InvalidPathException:

이런 오류가 나타나 해결방법을 공유하고자 합니다.

 

오류내용
Exception has occurred: SystemError
java.nio.file.InvalidPathException: Illegal char <*> at index 54: C:\Users\user\anaconda3\Lib\site-packages\konlpy\java\*
  File "C:\\1.py", line 12, in <module>

 

오류원인

jpype1 버전 오류

 

해결방법

최신 버전 jpype를 다운로드하여 프롬프트에서 실행해 보았지만 그래도 같은 오류가 나서

(JPype1-1.3.0-cp38-cp38-win_amd64.whl를 다운로드하였음)

결국 Visual Studio Code 터미널에 

pip install "jpype1==1.2.0"

라고 jpype1 1.2.0 버전을 설치하고 코드 실행하니 문제없이 돌아감을 확인할 수 있었습니다.

 

마무리

이 오류 때문에 하루 넘게 고민했는데 해결방법은 간단해서 다른 사람도 위와 같은 오류가 났다면

위의 방법으로 금방 해결하시길 바라는 마음에서 공유합니다 :)

다른 오류 나타나면 댓글로 공유해주세요 ㅎㅎ

반응형
반응형

저번 게시물에 이어 OPEN API를 이용해 코로나 확진자 수를 bar_chart_race로 시각화 해 보겠습니다.

Preview

Preview

공공데이터 OPENAPI를 이용해 데이터를 가져오는 방법은 아래의 링크를 참고하여 주세요.

 

[python] 공공데이터 OPEN API의 xml 을 DataFrame으로 변환하기(feat. 코로나 확진자 수)

안녕하세요~! 오늘은 공공데이터 openAPI의 xml을 Pandas DataFrame으로 변환하여 보도록 하겠습니다. json에서 DataFrame으로의 변환은 여기를 클릭해서 확인해 주세요 :) step1. 데이터 활용신청하기 공공데

wonhwa.tistory.com

 

step1. 데이터 준비

저번 게시물을 통해 만든

전국 코로나 확진자 수(2020년도~2021년도 11월 3일까지) 데이터인 'corona_kr.csv' 파일을 불러와줍니다.

import pandas as pd
import bar_chart_race as bcr

#csv파일 불러오기(코로나 전국 확진자)
corona_csv=pd.read_csv('corona_kr.csv')
print(corona_csv.head(19))

이렇게 많은 컬럼 값에 각 값이 들어가있습니다.

각 컬럼의 의미는 아래와 같습니다.(공공데이터 포털에서 확인 가능합니다.)

각 컬럼 값 정보
SEQ : 게시글번호(국내 시도별 발생현황 고유값)
CREATE_DT:  등록일시분초
DEATH_CNT:  사망자 수
GUBUN:  시도명(한글)
GUBUN_CN:   시도명(중국어)
gubunEn: 시도명(영어)
INC_DEC: 전일대비 증감 수
ISOL_CLEAR_CNT: 격리 해제 수
QUR_RATE: 10만명당 발생률
STD_DAY: 기준일시
UPDATE_DT: 수정일시분초
DEF_CNT: 확진자 수
ISOL_ING_CNT: 격리중 환자수
OVER_FLOW_CNT: 해외유입 수
LOCAL_OCC_CNT: 지역발생 수
step2. 시각화를 위한 데이터 전처리하기

여기서 시도별 확진자 수 시각화를 하기 위해

확진자 수, 업데이트날짜, 시도명(영어) 컬럼 값만 남기고 나머지는 지워보겠습니다.

#필요한 데이터만 남기고 지우기
corona = corona_csv[['createDt','defCnt','gubunEn']] # 등록일시분초, 확진자 수, 시도명(영어)
print(corona.head(19))

출력:

여기서 날짜 - 시도명 - 확진자 순으로 컬럼 순서를 바꿔 주도록 하겠습니다.

#열 순서 바꾸기 (등록일시, 시도명, 확진자 수 순)
corona = corona[['createDt','gubunEn','defCnt']]
print(corona.head(19))

위처럼 시간 - 이름 - 확진자 수 로 순서 배치가 잘 되었음을 확인할 수 있습니다.

다음으로, 시각화할때 관련없는 검역(Lazaretto)과 총합(Total)행을 지워주도록 하겠습니다.

 gubunEn(시도 영어명)이 Lazaretto, Total 이 아닌 행만 남기는 조건을 달아 보도록 하겠습니다.

#필요없는 데이터 지우기(검역Lazaretto, 토탈Total)
condition = (corona.gubunEn != 'Lazaretto') & (corona.gubunEn !='Total')
corona = corona[condition]
print(corona.head(17))

출력:

위 사진과 같이 잘 지워졌음을 확인할 수 있습니다.

이제 열값을 도시명으로 하고 값을 확진자 수로 피벗팅 해보겠습니다.

그리고 그 후 NaN값이 있는지 확인해 보도록 하겠습니다.

# 열값을 지역(gubunEn)으로, 값을 확진자 수(defCnt)로 하여 피봇팅하기
corona_df = corona.pivot_table(values = 'defCnt', index = ['createDt'], columns='gubunEn')

#nan값 있는지 확인 True이면 null값이 있음
print(pd.isnull(corona_df))

출력:

중간중간 True가 있는 것을 보니 피벗후 데이터프레임에 NaN값이 있는 것을 확인 할 수 있습니다.

이 NaN값들을 모두 0으로 바꾸어주도록 하겠습니다.

# NaN값을 0으로 바꾸어 주기
corona_df.fillna(0,inplace=True)
print(corona_df.head())

출력:

그럼 이렇게 0.0으로 대체되었음을 확인할 수 있습니다.

이제 전처리 마지막 단계입니다.

bar_chart_race로 시각화하기 위해 다음행을 그 전 행의 누적하여 값을 나타내 주도록 하겠습니다.

# 확진자 수 누적값으로 만들어주기
corona_df.iloc[:,0:-1] = corona_df.iloc[:,0:-1].cumsum()
print(corona_df.head())

출력:

위 사진과 같이 누적값으로 변환이 되었습니다.

step3. bar_chart_race로 시각화하기
#bar_chart_race로 시각화하기
bcr.bar_chart_race(df = corona_df,
                    n_bars= 17,
                    sort='desc',
                    title='Corona in Korea',
                    filename='한국_코로나확진자.mp4')

시도명이 총 17개이므로 n_bars를 17로, 정렬(sort)은 내림차순으로 하여 큰 숫자부터 앞에 나타나도록 하였습니다.

title(제목)을 설정해주고 , 파일을 mp4로 저장하기 위해 filename을 설정해 주었습니다.

이번 데이터는 양이 많기 때문에 그래프를 생성하는데 시간이 오래 걸립니다.

이점 참고해 주세요.

또는 step2의 데이터 전처리 과정에서 시간 행을 줄이고 시각화 하시길 바랍니다.

출력:

 

2020년~2021년도 11월 3일까지 전국 코로나 확진자 수 시각화

[한글버전]

 

전체 코드
import pandas as pd
import bar_chart_race as bcr

#csv파일 불러오기(코로나 전국 확진자)
corona_csv=pd.read_csv('corona_kr.csv')

#print(corona_csv.head(19))

## 각 컬럼 값 ## (포털 문서에서 꼭 확인하세요)
"""
SEQ : 게시글번호(국내 시도별 발생현황 고유값)
CREATE_DT: 	등록일시분초
DEATH_CNT: 	사망자 수
GUBUN: 	시도명(한글)
GUBUN_CN: 	시도명(중국어)
gubunEn: 시도명(영어)
INC_DEC: 전일대비 증감 수
ISOL_CLEAR_CNT: 격리 해제 수
QUR_RATE: 10만명당 발생률
STD_DAY: 기준일시
UPDATE_DT: 수정일시분초
DEF_CNT: 확진자 수
ISOL_ING_CNT: 격리중 환자수
OVER_FLOW_CNT: 해외유입 수
LOCAL_OCC_CNT: 지역발생 수

""" 

#필요한 데이터만 남기고 지우기
corona = corona_csv[['createDt','defCnt','gubunEn']] # 등록일시분초, 확진자 수, 시도명(영어)
#print(corona.head(19))

#열 순서 바꾸기 (등록일시, 시도명, 확진자 수 순)
corona = corona[['createDt','gubunEn','defCnt']]
#print(corona.head(19))

#필요없는 데이터 지우기(검역Lazaretto, 토탈Total)
condition = (corona.gubunEn != 'Lazaretto') & (corona.gubunEn !='Total')
corona = corona[condition]
#print(corona.head(17))

# 열값을 지역(gubunEn)으로, 값을 확진자 수(defCnt)로 하여 피봇팅하기
corona_df = corona.pivot_table(values = 'defCnt', index = ['createDt'], columns='gubunEn')

#nan값 있는지 확인 True이면 null값이 있음
#print(pd.isnull(corona_df))

# NaN값을 0으로 바꾸어 주기
corona_df.fillna(0,inplace=True)
#print(corona_df.head())

# 확진자 수 누적값으로 만들어주기
corona_df.iloc[:,0:-1] = corona_df.iloc[:,0:-1].cumsum()
print(corona_df.head())

#bar_chart_race로 시각화하기
bcr.bar_chart_race(df = corona_df,
                    n_bars= 17,
                    sort='desc',
                    title='Corona in Korea',
                    filename='한국_코로나확진자.mp4')

아래는 한글 버전입니다.

###한글버전###
import pandas as pd
import bar_chart_race as bcr
from matplotlib import font_manager,rc

# 한글 폰트 설정
font_location = 'C:/Windows/Fonts/MALGUNSL.TTF' #맑은고딕
font_name = font_manager.FontProperties(fname=font_location).get_name()
rc('font',family=font_name)

#csv파일 불러오기(코로나 전국 확진자)
corona_csv=pd.read_csv('corona_kr.csv')

#필요한 데이터만 남기고 지우기
corona = corona_csv[['createDt','defCnt','gubun']] # 등록일시분초, 확진자 수, 시도명(한글)

#열 순서 바꾸기 (등록일시, 시도명, 확진자 수 순)
corona = corona[['createDt','gubun','defCnt']]

#필요없는 데이터 지우기(검역Lazaretto, 합계Total)
condition = (corona.gubun != '검역') & (corona.gubun !='합계')
corona = corona[condition]

# 열값을 지역(gubun)으로, 값을 확진자 수(defCnt)로 하여 피봇팅하기
corona_df = corona.pivot_table(values = 'defCnt', index = ['createDt'], columns='gubun')

# NaN값을 0으로 바꾸어 주기
corona_df.fillna(0,inplace=True)

# 확진자 수 누적값으로 만들어주기
corona_df.iloc[:,0:-1] = corona_df.iloc[:,0:-1].cumsum()

#bar_chart_race로 시각화하기
bcr.bar_chart_race(df = corona_df,
                    shared_fontdict={'family':font_name},
                    n_bars= 17,
                    sort='desc',
                    title='한국 코로나 누적 확진자(2019-2021)',
                    filename='한국_코로나확진자_한글.mp4')
코드 파일

corona_bar_chart_race.py
0.00MB
bar_chart_race(kor).py
0.00MB

마무리

저번 시각화에 이어 오늘은 공공데이터 OPEN API를 이용하여 수집한 데이터를 토대로 시각화를 해 보았습니다.

거의 2년치를 시각화하느라 시간이 꽤 걸렸는데요. 

공공 데이터를 이용해 다른 분야도 위 게시글을 활용하여 시각화 해보시길 바랍니다 :)

질문은 댓글로 남겨주세요 ^ㅇ^

 

++ 22.07.05 한국어 버전 추가

반응형
반응형

안녕하세요! 

그전까지는 주피터 노트북을 이용하여 코드 작성을 많이 하였는데요

이제 프로젝트를 진행하다 보면 Visual Studio Code를 이용하는게 효율적일 때가 있습니다.

git도 연동이 가능하고 수정사항 표시 등 여러 유용 기능도 있습니다.

Visual Studio Code를 이용해 개발환경 구축도 하고, 파이썬 뿐만이 아니라 다른 프로그래밍언어(C, Java 등...)도 사용이 가능하니까 설치하여 보시고 필요시 사용하시는 것을 추천합니다 ㅎㅎ

물론 여기서도 주피터 노트북 사용이 가능합니다.

 step1. Visual Studio Code 설치하기

https://code.visualstudio.com/

 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

위의 링크를 클릭하시고 

본인 컴퓨터 운영체제와 맞는 파일을 다운로드해 주세요.

저는 Windows x64의 Stable 을 다운받았습니다.

다운로드 한 셋업파일을 실행시켜 주세요.

동의하기> 계속>계속 을 눌러 설치를 완료해 주세요.

step2. python install하기

Visual Studio Code에 들어가셔서 왼쪽 끝, 아래서 두번째 네모 아이콘을 선택 후

Python을 검색하시고 나오는 첫번째 검색결과를 클릭하고 Install을 클릭하여 설치해 주세요.

저는 이미 설치가 되어있기때문에 아래 사진에는 Uninstall로 나와 있습니다.

step3. Anaconda interpreter 설정하기

그 후 좌측 상단의 File> OPEN Folder 을 눌러 폴더를 하나 열어주세요.

저는 바탕화면에 web_AI 폴더 안에 Python_code라는 폴더를 하나 만들어서 그 폴더를 열어보겠습니다.

그러면  아까 선택한 Python_code 폴더가 왼쪽 창에 뜹니다.

여기서 오른쪽에 네모+ 아이콘을 클릭하여 파일을 추가해 주면 파일의 이름을 입력하라는 창이 뜹니다.

이곳에 test.py 라는 이름의 파이썬 파일을 만들어 보겠습니다.

위와 같이 test.py 파일이 만들어졌습니다.

여기서 Ctrl + Shitf + P 키를 누르면 아래와 같이 창이 뜨는데 거기서

Python: Select Interpreter를 클릭해 줍니다.

그 후 나오는 창에서 Python ~version 64-bit('base': conda)를 클릭하여 줍니다.

아나콘다를 설치했을 때 아래와 같이 나오므로 미설치되어 있는 분들은 아나콘다 설치 후 실행해 주시길 바랍니다.

그러면 아나콘다 interpreter 설정이 완료되었습니다.

그 후 Terminal > New Terminal을 클릭해 주세요.

그러면 하단에 Terminal 창이 나타나는데 (프롬프트와 비슷한 역할을 합니다.)

아래에 conda activate base가 나온다면 잘 작동이 되고 있는 겁니다.

이제 예시로 print('Hello World!')를 작성하고 F5키를 누른 후 Python File을 클릭하면,

아래 터미널에 Hello World!가 잘 출력됨을 확인할 수 있습니다.

한 줄 실행 시에는 Shitf+ Enter를 눌러주세요.

전체실행F5를 누르면 코드 실행이 됩니다. :)

Visual Studio Code를 이용해서 코딩 테스트 연습도 할 수 있으니(주피터 노트북보다 실행 시간이 빠른 것으로 알고 있습니다.)  다운받아 설치하여 사용해 보시길 바랍니다. :)

반응형
반응형

안녕하세요~! 오늘은 공공데이터 openAPI의 xml을 Pandas DataFrame으로 변환하여 보도록 하겠습니다.
json에서 DataFrame으로의 변환은 여기를 클릭해서 확인해 주세요 :)

step1. 데이터 활용신청하기

공공데이터 포털

 

공공데이터 포털

국가에서 보유하고 있는 다양한 데이터를『공공데이터의 제공 및 이용 활성화에 관한 법률(제11956호)』에 따라 개방하여 국민들이 보다 쉽고 용이하게 공유•활용할 수 있도록 공공데이터(Datase

www.data.go.kr

위 사이트에 접속 후 로그인하여 주세요.
여기서 '코로나'를 검색해 주세요.
그 후 스크롤 다운을 하셔서 아래의 내용을 찾으신 후 API 활용신청을 해 주세요.

https://www.data.go.kr/data/15043378/openapi.do

 

공공데이터활용지원센터_보건복지부 코로나19 시·도발생 현황

코로나19감염증으로 인한 시.도별 신규확진자,신규사망자,격리중인환자수,격리해제환자수등에 대한 현황자료 (이 제공자료는 관련 발생 상황에 대한 정보를 신속 투명하게 공개하기 위한 것으

www.data.go.kr

또는 위의 링크를 클릭하셔도 됩니다 :)
활용신청을 했다면 마이페이지에 들어가 주세요 :)

오픈 API > 개발계정> 공공데이터 활용지원센터_보건복지부 코로나19 시.도 발생 현황을 클릭해 주세요.

그 후 상세설명 클릭하여 요청 값 및 출력 값(컬럼)을 확인해 주세요.
각각의 컬럼 값에 어떤 내용이 있는지 확인하기 위해서 꼭 필요하기 때문에 잘 읽어주세요.

스크롤 다운을 하면 아래의 샘플코드> Python을 클릭하여 코드를 참고하여 xml을 불러오면 됩니다.

 

step2. API를 사용하여 xml 불러오기

이제부터 데이터를 요청하는 코드를 작성해 보도록 하겠습니다.

# 모듈 import
import requests
import pprint

#인증키 입력
encoding = '발급받은 인코딩 인증키를 복사하여 붙여넣기 해 주세요.'
decoding = '발급받은 디코딩 인증키를 복사하여 붙여넣기 해 주세요.'

#url 입력
url = 'http://openapi.data.go.kr/openapi/service/rest/Covid19/getCovid19SidoInfStateJson'
params ={'serviceKey' : decoding , 
'pageNo' : '1', 
'numOfRows' : '10', 
'startCreateDt' : '2020', 
'endCreateDt' : '20211103' }

response = requests.get(url, params=params)

# xml 내용
content = response.text

# 깔끔한 출력 위한 코드
pp = pprint.PrettyPrinter(indent=4)
#print(pp.pprint(content))

위의 내용까지는 전 게시글의 내용과 비슷합니다.
서비스키에 들어갈 수 있는 인증키로는 인코딩과 디코딩이 있는데 인코딩으로 실행하였을 때 오류가 나서 디코딩 인증키를 넣어 요청하였습니다.

step3. xml을 DataFrame으로 변환하기

xml 문서는 <item>안에 각 값이 태그 형식<>으로 들어 있습니다.
이 점을 이용해 뷰티플수프를 이용하여 파싱해보도록 하겠습니다.

### xml을 DataFrame으로 변환하기 ###
from os import name
import xml.etree.ElementTree as et
import pandas as pd
import bs4
from lxml import html
from urllib.parse import urlencode, quote_plus, unquote

## 각 컬럼 값 ## (포털 문서에서 꼭 확인하세요)
"""
SEQ : 게시글번호(국내 시도별 발생현황 고유값)
CREATE_DT: 	등록일시분초
DEATH_CNT: 	사망자 수
GUBUN: 	시도명(한글)
GUBUN_CN: 	시도명(중국어)
gubunEn: 시도명(영어)
INC_DEC: 전일대비 증감 수
ISOL_CLEAR_CNT: 격리 해제 수
QUR_RATE: 10만명당 발생률
STD_DAY: 기준일시
UPDATE_DT: 수정일시분초
DEF_CNT: 확진자 수
ISOL_ING_CNT: 격리중 환자수
OVER_FLOW_CNT: 해외유입 수
LOCAL_OCC_CNT: 지역발생 수

""" 

#bs4 사용하여 item 태그 분리

xml_obj = bs4.BeautifulSoup(content,'lxml-xml')
rows = xml_obj.findAll('item')
print(rows)

출력:

위의 내용만으로 한 눈에 어떤 정보가 있는지 보기 힘들기 때문에 데이터 프레임으로 만들기 전 이에 필요한
각각의 행값, 열 이름값, 데이터값을 추출하는 코드를 작성해 보겠습니다.

# 각 행의 컬럼, 이름, 값을 가지는 리스트 만들기
row_list = [] # 행값
name_list = [] # 열이름값
value_list = [] #데이터값

# xml 안의 데이터 수집
for i in range(0, len(rows)):
    columns = rows[i].find_all()
    #첫째 행 데이터 수집
    for j in range(0,len(columns)):
        if i ==0:
            # 컬럼 이름 값 저장
            name_list.append(columns[j].name)
        # 컬럼의 각 데이터 값 저장
        value_list.append(columns[j].text)
    # 각 행의 value값 전체 저장
    row_list.append(value_list)
    # 데이터 리스트 값 초기화
    value_list=[]

여기서 name_list는 열 이름들을 가지고 있고, row_list는 한 행의 값을 가지고 있습니다.
이제 위 변수들에 저장된 내용을 가지고 DataFrame으로 만들어 보겠습니다.

#xml값 DataFrame으로 만들기
corona_df = pd.DataFrame(row_list, columns=name_list)
print(corona_df.head(19))

가끔 데이터 프레임을 만들 때  Assertion Error가 나는 경우가 있는데 이때는 columns를 사용하지 마시고 df를 만들면 됩니다.

#xml값 DataFrame으로 만들기
#Assertion Error가 난 경우
corona_df = pd.DataFrame(row_list)
# 이후에 컬럼을 설정해 주세요.

출력:

깔끔하게 데이터프레임으로 만들어짐을 확인할 수 있습니다 :)
추가로 만들어진DataFrame을 csv파일로 저장하고 싶다면 아래의 코드를 추가하시면 됩니다.

#DataFrame CSV 파일로 저장
corona_df.to_csv('corona_kr.csv', encoding='utf-8-sig')

 

전체 코드
# 모듈 import
import requests
import pprint


#인증키 입력
encoding = '발급받은 인코딩 인증키를 복사하여 붙여넣기 해 주세요.'
decoding = '발급받은 디코딩 인증키를 복사하여 붙여넣기 해 주세요.'

#url 입력
url = 'http://openapi.data.go.kr/openapi/service/rest/Covid19/getCovid19SidoInfStateJson'
params ={'serviceKey' : decoding , 'pageNo' : '1', 'numOfRows' : '10', 'startCreateDt' : '2020', 'endCreateDt' : '20211103' }

response = requests.get(url, params=params)

# xml 내용
content = response.text

# 깔끔한 출력 위한 코드
pp = pprint.PrettyPrinter(indent=4)
#print(pp.pprint(content))

### xml을 DataFrame으로 변환하기 ###
from os import name
import xml.etree.ElementTree as et
import pandas as pd
import bs4
from lxml import html
from urllib.parse import urlencode, quote_plus, unquote

## 각 컬럼 값 ## (포털 문서에서 꼭 확인하세요)
"""
SEQ : 게시글번호(국내 시도별 발생현황 고유값)
CREATE_DT: 	등록일시분초
DEATH_CNT: 	사망자 수
GUBUN: 	시도명(한글)
GUBUN_CN: 	시도명(중국어)
gubunEn: 시도명(영어)
INC_DEC: 전일대비 증감 수
ISOL_CLEAR_CNT: 격리 해제 수
QUR_RATE: 10만명당 발생률
STD_DAY: 기준일시
UPDATE_DT: 수정일시분초
DEF_CNT: 확진자 수
ISOL_ING_CNT: 격리중 환자수
OVER_FLOW_CNT: 해외유입 수
LOCAL_OCC_CNT: 지역발생 수

""" 

#bs4 사용하여 item 태그 분리

xml_obj = bs4.BeautifulSoup(content,'lxml-xml')
rows = xml_obj.findAll('item')
print(rows)
"""
# 컬럼 값 조회용
columns = rows[0].find_all()
print(columns)
"""

# 각 행의 컬럼, 이름, 값을 가지는 리스트 만들기
row_list = [] # 행값
name_list = [] # 열이름값
value_list = [] #데이터값

# xml 안의 데이터 수집
for i in range(0, len(rows)):
    columns = rows[i].find_all()
    #첫째 행 데이터 수집
    for j in range(0,len(columns)):
        if i ==0:
            # 컬럼 이름 값 저장
            name_list.append(columns[j].name)
        # 컬럼의 각 데이터 값 저장
        value_list.append(columns[j].text)
    # 각 행의 value값 전체 저장
    row_list.append(value_list)
    # 데이터 리스트 값 초기화
    value_list=[]

#xml값 DataFrame으로 만들기
corona_df = pd.DataFrame(row_list, columns=name_list)
###assertion error의 경우###
###corona_df = pd.DataFrame(row_list)
print(corona_df.head(19)) 

#DataFrame CSV 파일로 저장
corona_df.to_csv('corona_kr.csv', encoding='utf-8-sig')

 

코드 파일

corona_DataFrame.py
0.00MB

참고 사이트

Python (파이썬) 공공데이터 수집 (Open API - XML)

 

Python (파이썬) 공공데이터 수집 (Open API - XML)

공공데이터포털의 특징은 자료를 활용을 요약하자면 1. 회원 가입 후 '사용자 인증키'를 생성해야한다. 2. 이후 원하는 데이터를 '활용 신청'을 해서 승인이 떨어지고 활용 권한을 획득해야한다

greendreamtrre.tistory.com

 

마무리

저번에는 json -> DataFrame 하는 방법을 공유하였고
이번에는 xml -> DataFrame 하는 방법을 공유하였습니다.
다음 시간에는 위에서 만든 corona_df를 가지고 bar_chart_race로 시각하여 보도록 하겠습니다 ^ㅇ^
이해 가지 않는 내용이나 질문이 있으면 댓글로 남겨 주세요 :)

반응형
반응형

안녕하세요! 오늘은 bar-chart-race(직역하면 막대그래프 경주)를 이용해서 시각화 하는 방법을 알려드리려고 합니다.

예제로 EPL 영국 프리미어 축구 리그 데이터를 활용하여 bar-chart-race 시각화를 해 보도록 하겠습니다.

 

step1. 필요한 데이터 준비

이번에 사용할 데이터는  영국 프리미어 축구 리그 EPL의 2010년부터 2021년까지의 데이터입니다.

데이터에는 각 팀의 시즌별 순위 및 득점 정보가 나와 있습니다.

데이터는 Kaggle에서 받을 수 있습니다.

여기를 클릭하여 EPL Standings 2010-2021.csv를 받아 주세요 :)

링크를 클릭하면 위와 같은 화면이 나타나는데 다운로드를 클릭하시면 데이터셋이 저장됩니다.

step2. FFmpeg 설치하기

다음으로 bar-chart-race를 구동할 때 필요한 FFmpeg를 설치하여 줍니다.

https://ffmpeg.org/download.html#build-windows

 

Download FFmpeg

If you find FFmpeg useful, you are welcome to contribute by donating. More downloading options Git Repositories Since FFmpeg is developed with Git, multiple repositories from developers and groups of developers are available. Release Verification All FFmpe

ffmpeg.org

위에 링크를 클릭한 후, 

파란 윈도우 아이콘 선택 후 Windows builds from gyan.dev를 클릭하여 줍니다.

그럼 위와 같은 화면이 나타납니다. 최신 버전을 사용하여도 되지만 안정적인 버전을 다운받아보도록 하겠습니다.

ffmpeg-4.4.1-full_build.7z를 클릭하여 다운받아주세요.

다운 받은 압축 파일을 압축 해제해 주세요. 저는 Program Files라는 곳에 파일을 이동시켜 압축해제 하였습니다.

압축 해제한 ffmpeg-4.4.1-full_build 폴더 이름은 ffmpeg으로 변경해 주세요.

그 후 ffmpeg> bin에 ffmpeg.exe, ffplay.exe, ffprobe.exe 가 있으면 준비는 거의 다 되었습니다.

윈도우 검색창에 시스템 환경 변수 편집을 타이핑하고 클릭하여 주세요.

위의 창에서 환경 변수를 클릭하여 줍니다.

user에 대한 사용자 변수 > Path > 편집을 클릭하여 주세요.

새로 만들기 > ffmpeg.exe 가 있는 주소 입력 > 확인을 차례대로 눌러주세요.

그 후 나머지 창들도 확인을 클릭하여 창을 닫아줍니다.

다음으로, windows + R 키를 누른 후 cmd를 입력후 엔터하여 명령 창을 열어 줍니다.

나오는 창에 ffmpeg을 쳤을때 위와 같이 나오면 잘 설치가 되었다는 뜻입니다. :)

step3. bar_chart_race 모듈 다운받기
pip install bar_chart_race

위의 코드를 아나콘다 프롬프트에서 실행해 bar_chart_race를 다운 받습니다.

기본적인 bar_chart_race에는 image label 기능이 없기 때문에 bar_chart_library에 기능이 추가된 파일로 교체하도록 하겠습니다.

https://github.com/andresberejnoi/bar_chart_race/tree/image_labels

 

GitHub - andresberejnoi/bar_chart_race: Create animated bar chart races in Python with matplotlib

Create animated bar chart races in Python with matplotlib - GitHub - andresberejnoi/bar_chart_race: Create animated bar chart races in Python with matplotlib

github.com

위의 사이트에 들어간 후,

Code 클릭 > Download ZIP을 클릭하여 파일을 다운 받은 후 압축을 풀어 줍니다.

bar_chart_race-image_labels > bar_chart_race에서 빨간 박스의 모든 .py파일을 복사해 주세요.

그 후 user > anaconda3 > Lib > site-packages > bar_chart_race 안에 복사한 파일을 아래와 같이 붙여주세요.

드디어 bar_chart_race를 사용하기 위한 모든 준비를 마쳤습니다.

step4. 데이터 전처리하기

처음에 다운받은 EPL Standings 2010-2021.csv를 전처리하여 bar_chart_race에 맞는 데이터로 바꾸어 봅시다.

#필요한 모듈 불러오기
#!pip install bar_chart_race as bcr
import pandas as pd
import numpy as np
import bar_chart_race as bcr
#필요한 데이터 셋 불러오기
# 주의할 점: 주소에 \를 //로 바꿔줄 것!
path = "C://Users//user//Desktop//blog//code//EPL_Standings_2010_2021.csv"
EPL = pd.read_csv(path)

# 요약출력
EPL.head()

파일 주소를 입력 할 때는 \//로 바꾸어 주세요. 그대로 복사 붙여넣기 하면 오류가 납니다.

출력:

위와 같이 파일의 내용이 나옵니다. 우리는 여기서 Season, Team, Pts(전체 포인트)만 사용하겠습니다.

# 필요한 데이터만 남기고 지우기
EPL = EPL[['Season','Team','Pts']]
EPL.head()

그러면 위와 같이 3개의 컬럼만 남습니다.

그 후 프리미어 축구 팀을 열로, 점수를 값으로 하여 피봇팅 해 주겠습니다.

#데이터를 알맞은 포맷으로 변형하기 - 피봇팅
df = EPL.pivot_table(values='Pts', index = ['Season'],columns='Team')
df.head()

결과를 보니 NaN값이 많이 있습니다. NaN이 있으면 점수 계산이 안되기 때문에 NaN 값을 0으로 바꾸어 주겠습니다.

# NaN값 0으로 바꾸어 주기
df.fillna(0,inplace=True)
df.sort_values(list(df.columns), inplace=True)
df = df.sort_index()
df.head()

어느 팀이 시간에 따라 제일 잘했는지 시각화하기 위해서는 시즌별 점수가 누적이 되어 나타나야 합니다.

예를 들어, 1시즌이 12점, 2시즌이 25점일 때, 표로는 1시즌 : 12, 2시즌: 12+25 = 37 ... 이런식으로 누적으로 표현되어야 bar_chart_race를 그릴 수 있습니다.

때문에 각 열의 값을 누적값으로 바꾸어 주겠습니다.

# 누적데이터로 각 축구팀의 데이터 값 바꾸기
df.iloc[:,0:-1] = df.iloc[:, 0:-1].cumsum()
df.head()

이렇게 누적 값이 만들어졌습니다.

이 파일에는 37개의 축구 클럽이 있는데 그중 시즌 별로 상위 10위 클럽만 남기고 나머지 팀은 정리하도록 하겠습니다.

# 37개의 클럽 중 시즌 별 top 10 클럽만 남기고 다른 데이터는 지우기
top_10_clubs= set()
for index, row in df.iterrows():
    top_10_clubs |= set(row[row>0].sort_values(ascending=False).head(10).index)

df = df[top_10_clubs]
df.head()

대략 20개의 팀으로 줄었습니다.

step 5. bar_chart_race 만들기

위에서 전처리한 데이터를 가지고 bar_chart_race를 그려보겠습니다.

우선 각 팀별 막대 그래프에 이미지를 추가해 주기 위해 지금 작성하고 있는 코드가 있는 폴더 안에 각 축구팀의 이미지를 추가하도록 하겠습니다.

그림 파일은 제가 미리 준비를 하였으니 아래의 파일을 다운받은 후 압출을 풀어 주세요.

bar_image_labels.zip
4.02MB

이때 주의할 점은 사진 이름이 df 파일에 있는 컬럼 명과 정확히 일치하여야 하고, png 파일이어야 합니다.

그리고 반드시 현재 작성하고 있는 코드와 같은 폴더에 위치시켜 주세요.

#bar chart race 그리기
bcr.bar_chart_race(df = df,
                   n_bars = 10,
                   sort='desc',
                   img_label_folder="bar_image_labels",
                   steps_per_period = 50,
                   title = 'TOP 10 EPL clubs(2010-2021)') #)#'TOP 6 TEAM in PL(1992-2017)'
                   #,filename = 'epl_10_clubs.mp4') #차트 레이스를 동영상으로 저장하고 싶을 때 사용

 

여기서 n_bars는 화면에 표시할 막대의 갯수, title은 제목, 그리고 파일을 저장하고 싶다면 file='파일이름.mp4'를 작성해 주시면 됩니다. :)

전체 코드
#필요한 모듈 불러오기
#!pip install bar_chart_race as bcr
import pandas as pd
import numpy as np
import bar_chart_race as bcr

#필요한 데이터 셋 불러오기
# 주의할 점: 주소에 \를 //로 바꿔줄 것!
path = "C://Users//user//Desktop//blog//code//EPL_Standings_2010_2021.csv"
EPL = pd.read_csv(path)

# 요약출력
EPL.head()

# 필요한 데이터만 남기고 지우기
EPL = EPL[['Season','Team','Pts']]
EPL.head()

#데이터를 알맞은 포맷으로 변형하기 - 피봇팅
df = EPL.pivot_table(values='Pts', index = ['Season'],columns='Team')
df.head()

# NaN값 0으로 바꾸어 주기
df.fillna(0,inplace=True)
df.sort_values(list(df.columns), inplace=True)
df = df.sort_index()
df.head()

# 누적데이터로 각 축구팀의 데이터 값 바꾸기
df.iloc[:,0:-1] = df.iloc[:, 0:-1].cumsum()
df.head()

# 37개의 클럽 중 시즌 별 top 10 클럽만 남기고 다른 데이터는 지우기
top_10_clubs= set()
for index, row in df.iterrows():
    top_10_clubs |= set(row[row>0].sort_values(ascending=False).head(10).index)

df = df[top_10_clubs]
df.head()

#bar chart race 그리기
bcr.bar_chart_race(df = df,
                   n_bars = 10,
                   sort='desc',
                   img_label_folder="bar_image_labels",
                   steps_per_period = 50,
                   title = 'TOP 10 EPL clubs(2010-2021)') #)#'TOP 6 TEAM in PL(1992-2017)'
                   #,filename = 'epl_10_clubs.mp4') #차트 레이스를 동영상으로 저장하고 싶을 때 사용
코드 파일

Bar_chart_race_EPL.ipynb
1.08MB

마무리

오늘 이렇게 움직이는 그래프를 그려 보았는데요 한국어 자료가 거의 없어 여러 외국 사이트를 참고하고 

bar_chart_race를 사용하기 위한 설치 작업이 많아 시간이 오래 걸렸네요. 

그래도 만들고 결과를 보니 재밌었습니다.

다음에는 API를 이용하여 코로나 확진자 관련 그래프를 그려도 좋을 것 같다는 생각이 듭니다 ㅎㅎ

질문이나 좋은 의견이 있으면 댓글로 남겨주세요 :-)

 

++22.07.04 ffmpeg 설치방법 수정 완료.

반응형
반응형

데이터 분석을 하다 보면 pandas를 필수적으로 쓰게 되는데

원본 데이터 값 자체가 양이 많기도 하고 데이터 타입 자체도 통일 성 없이 한 열 값 안에 

int, float, str 타입이 섞여 있기도 한다.

예시데이터

위의 경우 인허가일자와 휴업 일자가 문자열도 섞여있고 중간에 NaN값, 스트링 안에 필요 없는 부호, 빈 값까지..

총체적 난국임을 알 수 있다.  위의 데이터를 pandas를 사용해서 깔끔하게

전부 int(정수)로 변환하여 보겠다.

#예시 데이터 프레임
import pandas as pd
from numpy import NaN, NAN, nan #누락값 넣기 위한 모듈 불러오기

df = pd.DataFrame({'구분':[1,2,3,4,5,6], 
                   '인허가일자':[2016312,'2020.02.01',201603,99991230,1980,192012],
                   '휴업일자':[20160312.0,'2020 320',201603.0,NaN,'2020-02-22','']})
#df = df.set_index('구분')
df

출력:

step1. 빈칸을 NaN으로 채워주기

# 비어 있는 값을 NaN으로 바꾸기
df = df.replace(r'^\s*$',NaN, regex=True)
df

출력:

이렇게 빈 칸을 NaN으로 채워준다.

step 2. NaN을 다른 값으로 변경해주기

#누락값 처리 NaN을 다른 값으로 변경하기
df = df.fillna(0) #다른 값 변경시 .fillna(변경할 숫자).iloc[행위치, 열위치] 입력하여 변경
df

출력:

그러면 NaN값이 0으로 채워짐을 확인할 수 있다.

step3. 문자열을 정수로 변환하기

이제 문자열을 정수로 변환하여야 하는데

우선 스트링 값을 가지는 곳에 특수문자와 공백을 제거 후 

pandas apply를 이용하여 데이터 프레임에 함수를 한 번에 적용해주도록 하겠다.

#문자열을 정수로 변경하기
import re
#string의 특수문자 제거하는 함수
def cleanString(x):
    x1 = ''
    if type(x1) == type(x):
        x = re.sub('[-=.#/?:$}]', '', x) #특수문자 제거
        x1 = x.replace(" ","") #공백제거
        return int(x1)
    else:
        return x

# 인허가일자 str int로 변환하기
df['인허가일자']=df['인허가일자'].apply(cleanString)
# 휴업일자 str int로 변환하기
df['휴업일자']=df['휴업일자'].apply(cleanString)
#휴업일자 float타입을 int로 바꿔주기
df['휴업일자'] =df['휴업일자'].astype('int64')

df

출력:

그럼 이렇게 깔끔하게 모두 정수로 변환이 되었음을 확인할 수 있다. :)

반응형

+ Recent posts