반응형
코로나 데이터를 인터넷에서 자동으로 다운로드하고, 이 데이터를 이용해서 국가별 코로나 신규 확진자 및 누적 확진자 추이 그래프를 그리는 프로그램을 작성해보겠다. (아래 그림과 같은)
코로나 데이터
코로나 데이터는 ECDC 사이트를 이용하도록 하겠다. 여기서는 매일 전 세계 코로나 데이터를 갱신해서 올려주고, 그 데이터를 무료로 다운로드할 수 있다.
- ECDC 사이트: https://data.europa.eu/
- 엑셀파일 자동 다운 링크: https://www.ecdc.europa.eu/sites/default/files/documents/COVID-19-geographic-disbtribution-worldwide.xlsx
프로그램 구상
- 프로그램은 파이썬을 사용해서 할 것이고, 소스는 .py로도 만들고, 주피터에서 돌릴 수 있도록 .ipynb로도 만들 것이다.
- 코로나 데이터는, 이미 xlsx가 있으면 받아내리지 않도록 하자.
- 미리 지정한 국가에 대해서 자동으로 그래프를 그리게 하자. 국가 지정은, 소스 코드의 제일 윗부분에 const로 지정하는 것으로.
프로그램 작성
1) 오늘 날짜를 기준으로 엑셀 파일명을 정하고, 이 엑셀이 로컬에 이미 있으면 다운 안받고, 없으면 받게 한다.
- 오늘 날짜는 datetime.date.today()를 이용해서 알아내고, strftime을 이용해서 스트링으로 바꾼다.
- 파일 존재 여부는 os.path.exitst 이용
- 다운로드하는 것은 download_covid_file이라는 함수를 만들어 사용
- 최종 리턴 값은, pandas.read_excel로 엑셀을 읽어서 DataFrame을 리턴
--> xlrd 패키지가 없으면 설치해야 동작함. pip install xlrd
import os
from datetime import date
def get_corona_data():
today_covid_file = date.today().strftime("%Y%m%d") + "_corona.xlsx"
if not os.path.exists(today_covid_file):
download_covid_file(today_covid_file)
return pd.read_excel(today_covid_file)
2) 인터넷에서 엑셀 파일 다운로드는 requests.get 함수를 이용
- 저장하는 것은 그냥 현재 폴더에 저장
- SSL 인증서 검증은 하지 않는 것으로. requests.get(...., verify=False)
import requests
def download_covid_file(covid_file):
covid_xls_url = 'https://www.ecdc.europa.eu/sites/default/files/documents/COVID-19-geographic-disbtribution-worldwide.xlsx'
req = requests.get(covid_xls_url, allow_redirects=True, vefify=False)
open(covid_file, 'wb').write(req.content)
3) 국가에 대한 데이터만 뽑아내기
- pandas 기능을 이용해서 전 세계 데이터 중에서, 해당 국가에 대한 데이터만 취출
- 문자열로 되어 있는 칼럼은 pandas.to_datetime을 이용해서 Date형식으로 변경
- 2020.1.1일부터 현재까지의 데이터 취출
def get_data_by_country(df_world, country='South_Korea'):
df = df_world[df_world['countriesAndTerritories']==country][['dateRep','day','month','year','cases']].reset_index(drop=True)
df['dateRep'] = df['dateRep'].apply(lambda x: pd.to_datetime(x, format='%Y-%m-%d'))
df['week']=df['dateRep'].dt.week
df['weekday']=df['dateRep'].dt.weekday
df = df[['dateRep','day','month','year','weekday','week','cases']]
df = df.sort_values('dateRep', ascending=True).reset_index(drop=True)
index_2020 = df['year'].eq(2020).idxmax() #2020년이 처음 시작하는 index
df = df.iloc[index_2020:] #from 2020.01.01
df['cumul_cases'] = df['cases'].cumsum()
return df
4) 차트형 그래프 그리기
- x축은 날자
- y축은, 왼쪽은 일별 확진자 수, 오른쪽은 누적 확진자 수를 축으로 하게끔(2개의 축): ax1.twinx() 이용
- 일별 확진자 수는 blue, 누적 확진자 수는 red
- 그래프 크기는 (20인치, 7인치): fig.set_size_inches(20,7)
import matplotlib as mpl
from matplotlib import pyplot as plt
def draw_covid_graph(df):
# set_hangul_font()
x = df['dateRep']
y1 = df['cases']
y2 = df['cumul_cases']
fig, ax1 = plt.subplots()
color1 = 'tab:blue'
ax1.set_xlabel('Date[day]')
ax1.set_ylabel('Daily Cases', color=color1)
ax1.plot(x,y1, color=color1, label='New Cases')
ax1.tick_params(axis='y', labelcolor=color1)
ax1.legend(loc='upper left')
# ax1.set_xticks(range(0,x.max()+1))
ax1.grid(linestyle='--')
ax2 = ax1.twinx()
color2 = 'tab:red'
ax2.set_ylabel('Cumulated Cases', color=color2)
ax2.plot(x,y2, color=color2, label='Cumulated Number of Cases')
ax2.tick_params(axis='y', labelcolor=color2)
ax2.legend(loc='upper right')
fig.set_size_inches(20,7)
# plt.grid(True,)
plt.show()
5) 실행 코드
df_world = get_corona_data() # 전 세계 국가별/일별 확진자/사망자 데이터
country='South_Korea'
df_country = get_data_by_country(df_world, country)
draw_covid_graph(df_country)
아래는, 위 코드를 주피터 노트북에서 실행한 모습이고, 소스는 downlaod_draw_chart.ipynb 참조
주피터에서의 실행 모습
In [9]:
import os
import requests
from datetime import date
import pandas as pd
# Download COVID19 data file from the ECDC site. It contains updated COVID cases and death number for all of the world.
def download_covid_file(covid_file):
covid_xls_url = 'https://www.ecdc.europa.eu/sites/default/files/documents/COVID-19-geographic-disbtribution-worldwide.xlsx'
req = requests.get(covid_xls_url, allow_redirects=True, verify=False)
open(covid_file, 'wb').write(req.content)
# Download COVID data file from the internet if there is no excel file for today's date.
def get_corona_data():
today_covid_file = date.today().strftime("%Y%m%d") + "_corona.xlsx"
if not os.path.exists(today_covid_file):
download_covid_file(today_covid_file)
return pd.read_excel(today_covid_file)
def get_data_by_country(df_world, country='South_Korea'):
df = df_world[df_world['countriesAndTerritories']==country][['dateRep','day','month','year','cases']].reset_index(drop=True)
df['dateRep'] = df['dateRep'].apply(lambda x: pd.to_datetime(x, format='%Y-%m-%d'))
# df['week']=df['dateRep'].dt.week
df['week']=df['dateRep'].dt.isocalendar().week
df['weekday']=df['dateRep'].dt.weekday
df = df[['dateRep','day','month','year','weekday','week','cases']]
df = df.sort_values('dateRep', ascending=True).reset_index(drop=True)
index_2020 = df['year'].eq(2020).idxmax() #2020년이 처음 시작하는 index
df = df.iloc[index_2020:] #from 2020.01.01
df['cumul_cases'] = df['cases'].cumsum()
return df
import matplotlib as mpl
from matplotlib import pyplot as plt
def draw_covid_graph(df):
# set_hangul_font()
x = df['dateRep']
y1 = df['cases']
y2 = df['cumul_cases']
fig, ax1 = plt.subplots()
color1 = 'tab:blue'
ax1.set_xlabel('Date[day]')
ax1.set_ylabel('Daily Cases', color=color1)
ax1.plot(x,y1, color=color1, label='New Cases')
ax1.tick_params(axis='y', labelcolor=color1)
ax1.legend(loc='upper left')
# ax1.set_xticks(range(0,x.max()+1))
ax1.grid(linestyle='--')
ax2 = ax1.twinx()
color2 = 'tab:red'
ax2.set_ylabel('Cumulated Cases', color=color2)
ax2.plot(x,y2, color=color2, label='Cumulated Number of Cases')
ax2.tick_params(axis='y', labelcolor=color2)
ax2.legend(loc='upper right')
fig.set_size_inches(20,7)
# plt.grid(True,)
plt.show()
In [10]:
df_world = get_corona_data() # 전 세계 국가별/일별 확진자/사망자 데이터
df_world['countriesAndTerritories'].unique()
Out[10]:
array(['Afghanistan', 'Albania', 'Algeria', 'Andorra', 'Angola',
'Anguilla', 'Antigua_and_Barbuda', 'Argentina', 'Armenia', 'Aruba',
'Australia', 'Austria', 'Azerbaijan', 'Bahamas', 'Bahrain',
'Bangladesh', 'Barbados', 'Belarus', 'Belgium', 'Belize', 'Benin',
'Bermuda', 'Bhutan', 'Bolivia',
'Bonaire, Saint Eustatius and Saba', 'Bosnia_and_Herzegovina',
'Botswana', 'Brazil', 'British_Virgin_Islands',
'Brunei_Darussalam', 'Bulgaria', 'Burkina_Faso', 'Burundi',
'Cambodia', 'Cameroon', 'Canada', 'Cape_Verde',
'Cases_on_an_international_conveyance_Japan', 'Cayman_Islands',
'Central_African_Republic', 'Chad', 'Chile', 'China', 'Colombia',
'Comoros', 'Congo', 'Costa_Rica', 'Cote_dIvoire', 'Croatia',
'Cuba', 'Curaçao', 'Cyprus', 'Czechia',
'Democratic_Republic_of_the_Congo', 'Denmark', 'Djibouti',
'Dominica', 'Dominican_Republic', 'Ecuador', 'Egypt',
'El_Salvador', 'Equatorial_Guinea', 'Eritrea', 'Estonia',
'Eswatini', 'Ethiopia', 'Falkland_Islands_(Malvinas)',
'Faroe_Islands', 'Fiji', 'Finland', 'France', 'French_Polynesia',
'Gabon', 'Gambia', 'Georgia', 'Germany', 'Ghana', 'Gibraltar',
'Greece', 'Greenland', 'Grenada', 'Guam', 'Guatemala', 'Guernsey',
'Guinea', 'Guinea_Bissau', 'Guyana', 'Haiti', 'Holy_See',
'Honduras', 'Hungary', 'Iceland', 'India', 'Indonesia', 'Iran',
'Iraq', 'Ireland', 'Isle_of_Man', 'Israel', 'Italy', 'Jamaica',
'Japan', 'Jersey', 'Jordan', 'Kazakhstan', 'Kenya', 'Kosovo',
'Kuwait', 'Kyrgyzstan', 'Laos', 'Latvia', 'Lebanon', 'Lesotho',
'Liberia', 'Libya', 'Liechtenstein', 'Lithuania', 'Luxembourg',
'Madagascar', 'Malawi', 'Malaysia', 'Maldives', 'Mali', 'Malta',
'Marshall_Islands', 'Mauritania', 'Mauritius', 'Mexico', 'Moldova',
'Monaco', 'Mongolia', 'Montenegro', 'Montserrat', 'Morocco',
'Mozambique', 'Myanmar', 'Namibia', 'Nepal', 'Netherlands',
'New_Caledonia', 'New_Zealand', 'Nicaragua', 'Niger', 'Nigeria',
'North_Macedonia', 'Northern_Mariana_Islands', 'Norway', 'Oman',
'Pakistan', 'Palestine', 'Panama', 'Papua_New_Guinea', 'Paraguay',
'Peru', 'Philippines', 'Poland', 'Portugal', 'Puerto_Rico',
'Qatar', 'Romania', 'Russia', 'Rwanda', 'Saint_Kitts_and_Nevis',
'Saint_Lucia', 'Saint_Vincent_and_the_Grenadines', 'San_Marino',
'Sao_Tome_and_Principe', 'Saudi_Arabia', 'Senegal', 'Serbia',
'Seychelles', 'Sierra_Leone', 'Singapore', 'Sint_Maarten',
'Slovakia', 'Slovenia', 'Solomon_Islands', 'Somalia',
'South_Africa', 'South_Korea', 'South_Sudan', 'Spain', 'Sri_Lanka',
'Sudan', 'Suriname', 'Sweden', 'Switzerland', 'Syria', 'Taiwan',
'Tajikistan', 'Thailand', 'Timor_Leste', 'Togo',
'Trinidad_and_Tobago', 'Tunisia', 'Turkey',
'Turks_and_Caicos_islands', 'Uganda', 'Ukraine',
'United_Arab_Emirates', 'United_Kingdom',
'United_Republic_of_Tanzania', 'United_States_of_America',
'United_States_Virgin_Islands', 'Uruguay', 'Uzbekistan', 'Vanuatu',
'Venezuela', 'Vietnam', 'Wallis_and_Futuna', 'Western_Sahara',
'Yemen', 'Zambia', 'Zimbabwe'], dtype=object)
In [11]:
country='South_Korea'
df_country = get_data_by_country(df_world, country)
df_country.head()
Out[11]:
dateRep | day | month | year | weekday | week | cases | cumul_cases | |
---|---|---|---|---|---|---|---|---|
1 | 2020-01-01 | 1 | 1 | 2020 | 2 | 1 | 0 | 0 |
2 | 2020-01-02 | 2 | 1 | 2020 | 3 | 1 | 0 | 0 |
3 | 2020-01-03 | 3 | 1 | 2020 | 4 | 1 | 0 | 0 |
4 | 2020-01-04 | 4 | 1 | 2020 | 5 | 1 | 0 | 0 |
5 | 2020-01-05 | 5 | 1 | 2020 | 6 | 1 | 0 | 0 |
In [12]:
draw_covid_graph(df_country)
-끝-
반응형
'Information > Corona19(COVID19)' 카테고리의 다른 글
코로나 확진자 수/ 사망자 수에 대한 물방울 차트(Bubble Chart) 애니메이션 (0) | 2020.12.10 |
---|---|
전세계 COVID19 확진자 수 분석 (2020.06.12 기준) (0) | 2020.06.13 |
Country ranking by Corona19 infection worldwide (0) | 2020.05.25 |
코로나19(Corona19, COVID19) 엑셀 데이터 얻기/가공하기(2/2) (0) | 2020.05.23 |
코로나19(Corona19, COVID19) 엑셀 데이터 얻기/가공하기(1/2) (0) | 2020.05.22 |