如何使用 Python 繪製 COVID-19 的全球擴散圖
對於一個全球旅行司空見慣的世界來說,疾病的傳播是一個真正令人擔憂的問題。一些組織會跟蹤重大的流行病(還有所有普遍的流行病),並將他們的跟蹤工作獲得的數據公開出來。不過,這些原始的數據對人來說可能很難處理,這就是為什麼數據科學如此重要的原因。比如,用 Python 和 Pandas 可視化 COVID-19 在全球範圍內的傳播路徑可能對這些數據的分析有所幫助。
最開始,當面對如此大數量的原始數據時可能難以下手。但當你開始處理數據之後,慢慢地就會發現一些處理數據的方式。下面是用於處理 COVID-19 數據的一些常見的情況:
- 從 GitHub 上下載 COVID-19 的國家每日傳播數據,保存為一個 Pandas 中的 DataFrame 對象。這時你需要使用 Python 中的 Pandas 庫。
- 處理並清理下載好的數據,使其滿足可視化數據的輸入格式。所下載的數據的情況很好(數據規整)。這個數據有一個問題是它用國家的名字來標識國家,但最好是使用三位數的 ISO 3 碼(國家代碼表)來標識國家。為了生成 ISO 3 碼,可是使用
pycountry
這個 Python 庫。生成了這些代碼之後,可以在原有的 DataFrame 上增加一列,然後用這些代碼填充進去。 - 最後為了實現可視化,使用 Plotly 庫中的
express
模塊。這篇文章是使用名為choropleth 的地圖(可在 Plotly 庫中獲得)來可視化該疾病在全球的傳播。
第一步:Corona 數據
從下面這個網站上下載最新的 corona 數據(LCTT 譯註:2020-12-14 仍可訪問,有牆):
我們之間將這個下載好的數據載入為 Pandas 的 DataFrame。Pandas 提供了一個函數, read_csv()
,可以直接使用 URL 讀取數據,並返回一個 DataFrame 對象,具體如下所示:
import pycountry
import plotly.express as px
import pandas as pd
URL_DATASET = r'https://raw.githubusercontent.com/datasets/covid-19/master/data/countries-aggregated.csv'
df1 = pd.read_csv(URL_DATASET)
print(df1.head(3)) # Get first 3 entries in the dataframe
print(df1.tail(3)) # Get last 3 entries in the dataframe
在 Jupyter 上的輸出截圖:
![Jupyter screenshot](/data/attachment/album/202012/20/005202ap39m52pp4z9hams.png "Jupyter screenshot")
從這個輸出可以看到這個 DataFrame(df1
)包括以下幾列數據:
Date
Country
Confirmed
Recovered
Dead
之後還可以看到 Date
這一列包含了從 1 月 22 日到 3 月 31 日的條目信息。這個數據是每天更新的,所以你會得到你當天的值。
第二步:清理和修改 DataFrame
我們要往這個 DataFrame 中增加一列數據,就是那個包含了 ISO 3 編碼。可以通過以下三步完成這個任務:
- 創建一個包含所有國家的列表。因為在
df1
的Country
列中,國家都是每個日期就重複一次。所以實際上Country
列中對每個國家就會有多個條目。我使用unique().tolist()
函數完成這個任務。 - 我使用
d_country_code
字典對象(初始為空),然後將其鍵設置為國家的名稱,然後它的值設置為其對應的 ISO 3 編碼。 - 我使用
pycountry.countries.search_fuzzy(country)
為每個國家生成 ISO 3 編碼。你需要明白的是這個函數的返回值是一個Country
對象的列表。我將這個函數的返回值賦給country_data
對象。以這個對象的第一個元素(序號0
)為例。這個
。這樣就能在找不到這些「國家/地區」對應的 ISO 3 編碼時給出一個輸出提示。實際上,你會發現這些「國家/地區」會在最後的輸出中用白色來表示。對象有一個
alpha_3屬性。所以我使用
country_data[0].alpha_3就能「獲得」第一個元素的 ISO 3 編碼。然而,在這個 DataFrame 中有些國家的名稱可能沒有對應的 ISO 3 編碼(比如有爭議的領土)。那麼對這些「國家/地區」,我就用一個空白字元串來替代 ISO 3 編碼。你也可以用一個
try-except代碼來替換這部分。
except中的語句可以寫:
print(『could not add ISO 3 code for ->', country) - 在獲得了每個國家的 ISO 3 編碼(有些是空白字元串)之後,我把這些國家的名稱(作為鍵)還有國家對應的 ISO 3 編碼(作為值)添加到之前的字典
d_country_code
中。可以使用 Python 中字典對象的update()
方法來完成這個任務。 - 在創建好了一個包含國家名稱和對應 ISO 3 編碼的字典之後,我使用一個簡單的循環將他們加入到 DataFrame 中。
第三步:使用 Plotly 可視化傳播路徑
choropleth 地圖是一個由彩色多邊形組成的地圖。它常常用來表示一個變數在空間中的變化。我們使用 Plotly 中的 px
模塊來創建 choropleth 圖,具體函數為:px.choropleth
。
這個函數的所包含的參數如下:
plotly.express.choropleth(data_frame=None, lat=None, lon=None, locations=None, locationmode=None, geojson=None, featureidkey=None, color=None, hover_name=None, hover_data=None, custom_data=None, animation_frame=None, animation_group=None, category_orders={}, labels={}, color_discrete_sequence=None, color_discrete_map={}, color_continuous_scale=None, range_color=None, color_continuous_midpoint=None, projection=None, scope=None, center=None, title=None, template=None, width=None, height=None)
choropleth()
這個函數還有幾點需要注意:
geojson
是一個geometry
對象(上面函數第六個參數)。這個對象有點讓人困擾,因為在函數文檔中沒有明確地提到這個對象。你可以提供,也可以不提供geojson
對象。如果你提供了geojson
對象,那麼這個對象就會被用來繪製地球特徵,如果不提供geojson
對象,那這個函數默認就會使用一個內建的geometry
對象。(在我們的實驗中,我們使用內建的geometry
對象,因此我們不會為geojson
參數提供值)- DataFrame 對象有一個
data_frame
屬性,在這裡我們先前就提供了一個我們創建好的df1
。 - 我們用
Confirmed
(確診數)來決定每個國家多邊形的顏色。 - 最後,我們
Date
列創建一個animation_frame
。這樣我們就能通過日期來劃分數據,國家的顏色會隨著Confirmed
的變化而變化。
最後完整的代碼如下:
import pycountry
import plotly.express as px
import pandas as pd
# ----------- Step 1 ---------URL_DATASET = r'https://raw.githubusercontent.com/datasets/covid-19/master/data/countries-aggregated.csv'
df1 = pd.read_csv(URL_DATASET)
# print(df1.head) # Uncomment to see what the dataframe is like
# ----------- Step 2 ---------list_countries = df1['Country'].unique().tolist()
# print(list_countries) # Uncomment to see list of countries
d_country_code = {} # To hold the country names and their ISO
for country in list_countries:
try:
country_data = pycountry.countries.search_fuzzy(country)
# country_data is a list of objects of class pycountry.db.Country
# The first item ie at index 0 of list is best fit
# object of class Country have an alpha_3 attribute
country_code = country_data[0].alpha_3
d_country_code.update({country: country_code})
except:
print('could not add ISO 3 code for ->', country)
# If could not find country, make ISO code ' '
d_country_code.update({country: ' '})
# print(d_country_code) # Uncomment to check dictionary
# create a new column iso_alpha in the df
# and fill it with appropriate iso 3 code
for k, v in d_country_code.items():
df1.loc[(df1.Country == k), 'iso_alpha'] = v
# print(df1.head) # Uncomment to confirm that ISO codes added
# ----------- Step 3 ---------fig = px.choropleth(data_frame = df1,
locations= "iso_alpha",
color= "Confirmed", # value in column 'Confirmed' determines color
hover_name= "Country",
color_continuous_scale= 'RdYlGn', # color scale red, yellow green
animation_frame= "Date")
fig.show()
你可以從這裡下載並運行完整代碼。
最後,這裡還有一些關於 Plotly 繪製 choropleth 圖的不錯的資源。
- https://github.com/plotly/plotly.py/blob/master/doc/python/choropleth-maps.md
- https://plotly.com/python/reference/#choropleth
via: https://opensource.com/article/20/4/python-map-covid-19
作者:AnuragGupta 選題:lujun9972 譯者:zhangxiangping 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive