參考文章:Visualise COVID-19 case data using Python, Dash and Plotly
程式網址:https://github.com/ploner/coronavirus-py
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | import dash import dash_core_components as dcc import dash_html_components as html import plotly.graph_objects as go from dash.dependencies import Input, Output import pandas as pd baseURL = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/" external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] tickFont = {'size':12, 'color':"rgb(30,30,30)", 'family':"Courier New, monospace"} def loadData(fileName, columnName): data = pd.read_csv(baseURL + fileName) \ .drop(['Lat', 'Long'], axis=1) \ .melt(id_vars=['Province/State', 'Country/Region'], var_name='date', value_name=columnName) \ .fillna('<all>') data['date'] = data['date'].astype('datetime64[ns]') return data allData = loadData("time_series_19-covid-Confirmed.csv", "CumConfirmed") \ .merge(loadData("time_series_19-covid-Deaths.csv", "CumDeaths")) \ .merge(loadData("time_series_19-covid-Recovered.csv", "CumRecovered")) countries = allData['Country/Region'].unique() countries.sort() app = dash.Dash(__name__, external_stylesheets=external_stylesheets) app.layout = html.Div( style={ 'font-family':"Courier New, monospace" }, children=[ html.H1('Case History of the Coronavirus (COVID-19)'), html.Div(className="row", children=[ html.Div(className="four columns", children=[ html.H5('Country'), dcc.Dropdown( id='country', options=[{'label':c, 'value':c} for c in countries], value='Italy' ) ]), html.Div(className="four columns", children=[ html.H5('State / Province'), dcc.Dropdown( id='state' ) ]), html.Div(className="four columns", children=[ html.H5('Selected Metrics'), dcc.Checklist( id='metrics', options=[{'label':m, 'value':m} for m in ['Confirmed', 'Deaths', 'Recovered']], value=['Confirmed', 'Deaths'] ) ]) ]), dcc.Graph( id="plot_new_metrics", config={ 'displayModeBar': False } ), dcc.Graph( id="plot_cum_metrics", config={ 'displayModeBar': False } ) ]) @app.callback( [Output('state', 'options'), Output('state', 'value')], [Input('country', 'value')] ) def update_states(country): states = list(allData.loc[allData['Country/Region'] == country]['Province/State'].unique()) states.insert(0, '<all>') states.sort() state_options = [{'label':s, 'value':s} for s in states] state_value = state_options[0]['value'] return state_options, state_value def nonreactive_data(country, state): data = allData.loc[allData['Country/Region'] == country] if state == '<all>': data = data.drop('Province/State', axis=1).groupby("date").sum().reset_index() else: data = data.loc[data['Province/State'] == state] newCases = data.select_dtypes(include='int64').diff().fillna(0) newCases.columns = [column.replace('Cum', 'New') for column in newCases.columns] data = data.join(newCases) data['dateStr'] = data['date'].dt.strftime('%b %d, %Y') return data def barchart(data, metrics, prefix="", yaxisTitle=""): figure = go.Figure(data=[ go.Bar( name=metric, x=data.date, y=data[prefix + metric], marker_line_color='rgb(0,0,0)', marker_line_width=1, marker_color={ 'Deaths':'rgb(200,30,30)', 'Recovered':'rgb(30,200,30)', 'Confirmed':'rgb(100,140,240)'}[metric] ) for metric in metrics ]) figure.update_layout( barmode='group', legend=dict(x=.05, y=0.95, font={'size':15}, bgcolor='rgba(240,240,240,0.5)'), plot_bgcolor='#FFFFFF', font=tickFont) \ .update_xaxes( title="", tickangle=-90, type='category', showgrid=True, gridcolor='#DDDDDD', tickfont=tickFont, ticktext=data.dateStr, tickvals=data.date) \ .update_yaxes( title=yaxisTitle, showgrid=True, gridcolor='#DDDDDD') return figure @app.callback( Output('plot_new_metrics', 'figure'), [Input('country', 'value'), Input('state', 'value'), Input('metrics', 'value')] ) def update_plot_new_metrics(country, state, metrics): data = nonreactive_data(country, state) return barchart(data, metrics, prefix="New", yaxisTitle="New Cases per Day") @app.callback( Output('plot_cum_metrics', 'figure'), [Input('country', 'value'), Input('state', 'value'), Input('metrics', 'value')] ) def update_plot_cum_metrics(country, state, metrics): data = nonreactive_data(country, state) return barchart(data, metrics, prefix="Cum", yaxisTitle="Cumulated Cases") if __name__ == '__main__': app.run_server(debug=True) |
程式解說:
程式第1-7行滙入所需要套件
程式第8行定義一個baseURL,數據位於約翰霍普金斯大學系統科學與工程中心(JHU / CSSE)的服務器上,讓我們可以按國家和地區下載冠狀病毒的病例數據。
程式第10行指定引用CSS的網址。
程式第12行設定字型等CSS樣式。
程式第14到20行定義函數loadData處理下載和一些基本轉換。
程式第22到24行載入案例數據含確診、死亡、康復等人數。
程式第26到27行過濾重複資料以及排序。
程式第29行建立儀錶板物件。
程式第31行到67行建立網頁的佈局
程式第69行到79行是回呼函式處理選擇國家時能列出各省的資訊。
程式第81行到91行是依照區域和省份等資訊列出COVID-19的資料。
程式第93行到109行是將資訊轉成條狀圖。
程式第111行到125行是回呼函式反應網站送來的資訊。
程式第127行到128行是主程式
沒有留言:
張貼留言