全球抗「疫」:用Python帶你了解世界疫情

2021-02-20 數據幫Club

最初,沒有人在意這場災難,這不過是一場山火,一次旱災,一個物種的滅絕,一座城市的消失,直到這場災難和每個人息息相關。

——《流浪地球》

2020年註定是讓人難忘的一年,一場「前所未有」的新冠肺炎疫情打亂了所有人的日常生活,每日上升的確診數讓人們陷入恐慌。但有時候,持續滾動的數字往往會讓人從最初的恐懼變成麻木,因此筆者今天會用Python把一個一個冰冷的數字變成一幅一幅生動的圖片,帶你更加具體的了解世界疫情。

通過本文,你會學到如何用Python做數據分析,數據可視化,畫世界疫情地圖,了解世界疫情。本次用到的數據我在前面文章分享過,具體見全球抗「疫」:各國疫情數據早知道。

下面我會詳細介紹如何使用這些數據,建議本文代碼在Jupyter notebook上運行,話不多說,Let『s go!

首先當然是導入必備的幾個包了

import pandas as pdimport numpy as np

然後就是導入數據,本次使用的數據是Github上一個項目裡的,也可以直接用pandas包導入,需要注意的是不能直接使用Github那個網址,否則會報錯,需要將前面部分改成https://raw.githubusercontent.com/,然後就是加入數據的目錄地址。數據主要是是三個文件,包含了疫情的確診數(confirmed),治癒數(recoved),死亡數(deaths),基本上每日會更新最新疫情數據。
confirmed = pd.read_csv('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv')recovered = pd.read_csv('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Recovered.csv')deaths = pd.read_csv('https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Deaths.csv')

數據已經導入了,讓我們來看看數據是啥樣的吧。head(5)是查看數據前五行;confirmed表裡面包含發生疫情的國家,經緯度,以及從2020年1月22日至今的每日的確診數;recovered表則記錄了治癒數;deaths表則記錄了死亡數。使用shape則可以列印出三個數據表的維度。每個都是(101,40)維,即101行,40列。
print(confirmed.shape)print(recovered.shape)print(deaths.shape)

前面我們已經搞清楚了數據,下面就是我們的正餐—數據可視化。這部分主要用到matplotlib這個繪圖包,至於繪製地圖,放在第三部分講。
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif']  = ['SimHei']   #用來正常顯示中文標籤plt.rcParams['axes.unicode_minus'] = False   #用來正常顯示負號

首先看看在我們的數據中,哪些地區發生了疫情。可以看出一共49個地區都有新冠肺炎病例。
countries = confirmed['Country/Region'].unique()print(countries)

接下來看看世界疫情發展趨勢,我們的數據還需要再整理下,要計算出每日所有地區新冠肺炎的確診數,治癒數,死亡數。
all_confirmed = np.sum(confirmed.iloc[:,4:])all_recovered = np.sum(recovered.iloc[:,4:])all_deaths = np.sum(deaths.iloc[:,4:])

plt.plot(all_confirmed,color = 'red',label = '確診',marker = 'o')plt.plot(all_recovered,color = 'blue',label = '治癒',marker = 'o')plt.plot(all_deaths,color = 'lime',label = '死亡',marker = 'o')plt.xticks(rotation = 45,size = 10)plt.yticks(size=20)plt.xlabel('時 間',size = 20)plt.ylabel('數 目',size = 20)plt.title('全球疫情變化趨勢',size = 30)plt.legend(loc = "upper left",fontsize = 20)plt.show()

可以看出,目前新冠肺炎確診病例還在持續增加,不過令人高興的是治癒數也在持續增長,死亡數很少,希望疫情拐點早日出現,疫情早日結束。下面看看新冠肺炎的死亡率,首先計算死亡率數據,然後就可以直接畫圖。
death_rate = (all_deaths/all_confirmed)*100plt.plot(death_rate,color = 'lime',label = '死亡',marker = 'o')plt.xticks(rotation = 45,size = 10)plt.yticks(size = 15)plt.xlabel('時 間',size = 20)plt.ylabel('死亡率',size = 20)plt.title('全球疫情死亡率',size = 30)

由於本次疫情主要發生在中國大陸,下面來具體研究下中國大陸的疫情情況,首先從全部數據中提取出中國大陸的數據。裡面包含了省份,以及每個省最新的確診數,治癒數,死亡數。
last_update = '2/26/20'  # 設置最新數據日期China_cases = confirmed[['Province/State',last_update]][confirmed['Country/Region'] == 'Mainland China']China_cases['recovered']=recovered[[last_update]][recovered['Country/Region']=='Mainland China']China_cases['deaths']=deaths[[last_update]][deaths['Country/Region']=='Mainland China']China_cases = China_cases.set_index('Province/State')China_cases = China_cases.rename(columns = {last_update:'confirmed'})

Mainland_china = China_cases.sort_values(by='confirmed',ascending=True)Mainland_china.plot(kind='barh', figsize=(20,30), color = ['red','blue','lime'], width=1, rot=2)plt.title('中國大陸各省市疫情數量', size=30)plt.ylabel('省/市',size=20)plt.xlabel('數量',size = 20)plt.yticks(size=20)plt.xticks(size=15)plt.legend(bbox_to_anchor=(0.95,0.95),fontsize = 20)

可以看到,湖北省三項數據高居第一位,且遠遠高於其他省份。下面看看中國大陸的治癒率和死亡率數據,數據使用下面的代碼即可計算出來,最終結果在recover_rate和death_rate裡。
confirmed_china = confirmed[confirmed['Country/Region']=='Mainland China']confirmed_china = np.sum(confirmed_china.iloc[:,4:])recovered_china = recovered[recovered['Country/Region'] == 'Mainland China']recovered_china = np.sum(recovered_china.iloc[:,4:])deaths_china = deaths[deaths['Country/Region'] == 'Mainland China']deaths_china = np.sum(deaths_china.iloc[:,4:])recover_rate = (recovered_china/confirmed_china)*100death_rate = (deaths_china/confirmed_china)*100

plt.plot(recover_rate, color = 'blue', label = '治癒率', marker = 'o')plt.plot(death_rate, color = 'lime', label = '死亡率', marker = 'o')

plt.title('中國大陸治癒率 VS 死亡率',size=30)plt.ylabel('數量',size=20)plt.xlabel('時間',size=20)plt.xticks(rotation=45,size=10)plt.yticks(size=15)plt.legend(loc = "upper left",fontsize = 20)

雖然在1月25日-1月31日期間死亡率略高於治癒率,但其他時間段,治癒率遠遠高於死亡率,這都得益於全國廣大醫務人員的不懈努力!那中國大陸其他地區這一情況咋樣呢?代碼大同小異,我們一起來看看,首先還是提取出其他地區的數據。
confirmed_others = confirmed[confirmed['Country/Region'] != 'Mainland China']confirmed_others = np.sum(confirmed_others.iloc[:,4:])recovered_others = recovered[recovered['Country/Region'] != 'Mainland China']recovered_others = np.sum(recovered_others.iloc[:,4:])deaths_others = deaths[deaths['Country/Region'] != 'Mainland China']deaths_others = np.sum(deaths_others.iloc[:,4:])recover_rate = (recovered_others/confirmed_others)*100death_rate = (deaths_others/confirmed_others)*100

plt.plot(recover_rate, color = 'blue', label = '治癒率', marker = 'o')plt.plot(death_rate, color = 'lime', label = '死亡率', marker = 'o')

plt.title('其他地區治癒率 VS 死亡率',size=30)plt.ylabel('數量',size=20)plt.xlabel('時間',size=20)plt.xticks(rotation=45,size=10)plt.yticks(size=15)plt.legend(loc = "upper left",fontsize = 20)

接下來看看其他地區疫情數量。首先還是提出其他地區的數據
others = confirmed[['Country/Region',last_update]][confirmed['Country/Region'] != 'Mainland China']others['recovered'] = recovered[[last_update]][recovered['Country/Region'] != 'Mainland China']others['death'] = deaths[[last_update]][deaths['Country/Region'] != 'Mainland China']others_countries = others.rename(columns = {last_update:'confirmed'})others_countries = others_countries.set_index('Country/Region')others_countries = others_countries.groupby('Country/Region').sum()

others_countries.sort_values(by = 'confirmed',ascending = True).plot(kind='barh', figsize=(20,30), color = ['red','blue','lime'], width=1, rot=2)plt.title('世界其他地區疫情數量', size=30)plt.ylabel('Country/Region',size = 20)plt.xlabel('數量',size = 20)plt.yticks(size=10)plt.xticks(size=15)plt.legend(bbox_to_anchor=(0.95,0.95),fontsize = 20)

從圖可以看到,韓國,義大利,日本這些地區也有很多新冠肺炎患者。想必看到這,大家已經厭煩了前面的折線圖,柱狀圖了,下面筆者將教大家如何畫出疫情地圖,將每個數據對應到地圖上聽起來是不是很好玩呢?這裡主要用到兩個python包,一個是folium包,這個包也是筆者最近才發現的繪圖包,類似於R語言繪圖裡的ggplot2,可以添加圖層來定義一個Map對象,最後以幾種方式將Map對象展現出來。這裡有一個詳細教程,感興趣的可以看看https://python-visualization.github.io/folium/。另一個包就是plotly了,這也是一個強大的繪圖包,詳細教程請看這裡https://plot.ly/python/plotly-express/。首先是folium包繪製地圖,import folium,只需要導入包就可以了,沒下載這個包的記得下載才能使用。我們在前面數據裡加入中國大陸的數據,並使用武漢的經緯度。
others=confirmed[['Country/Region','Lat','Long',last_update]][confirmed['Country/Region'] != 'Mainland China']others['recovered'] = recovered[[last_update]][recovered['Country/Region'] != 'Mainland China']others['death'] = deaths[[last_update]][deaths['Country/Region'] != 'Mainland China']others_countries = others.rename(columns = {last_update:'confirmed'})others_countries.loc['94'] = ['Mainland China',30.9756,112.2707,confirmed_china[-1],recovered_china[-1],deaths_china[-1]]

world_map = folium.Map(location=[10, -20], zoom_start=2.3,tiles='Stamen Toner')

上面一行是定義一個world_map對象;location的格式為[緯度,經度];zoom_start表示初始地圖的縮放尺寸,數值越大放大程度越大;tiles為地圖類型,用於控制繪圖調用的地圖樣式,默認為'OpenStreetMap',也有一些其他的內建地圖樣式,如'Stamen  Terrain'、'Stamen Toner'、'Mapbox Bright'、'Mapbox Control Room'等;也可以傳入'None'來繪製一個沒有風格的樸素地圖,或傳入一個URL來使用其它的自選osm。然後往world_map裡添加其他元素,注意這裡的for循環和最後的add_to是把經緯度點的信息一個一個的加進去
for lat, lon, value, name in zip(others_countries['Lat'], others_countries['Long'], others_countries['confirmed'], others_countries['Country/Region']):    folium.CircleMarker([lat, lon],                            radius=10,                            popup = ('<strong>Country</strong>: ' + str(name).capitalize() + '<br>'                                                            '<strong>Confirmed Cases</strong>: ' + str(value) + '<br>'),                                                    color='red',                                                                            fill_color='red',                                                    fill_opacity=0.7 ).add_to(world_map

popup:str型或folium.Popup()對象輸入,用於控制標記部件的具體樣式(folium內部自建了許多樣式),默認為None,即不顯示部件。代碼使用的是自定義的網頁樣式,其中<strong>表示加粗,<br>表示換行,以便將各個數據顯示出來。然後再運行world_map,即可出現下面的地圖樣式,這是一種可交互的地圖,可以隨意移動縮放,滑鼠點擊地圖上紅點,即可出現地區的疫情信息。下面我再教大家用plotly繪製每日疫情擴散地圖,首先是導入包
import plotly.express as px

在這裡,我想繪製每日疫情擴散地圖,我需要增加一列,裡面記錄了每天的日期,因此我們的數據還需要再重新整理下,這裡需要用的melt函數,它將列名轉換為列數據(columns name → column values),重構DataFrame,
confirmed = confirmed.melt(id_vars = ['Province/State', 'Country/Region', 'Lat', 'Long'], var_name='date',value_name = 'confirmed')

# value_vars:需要轉換的列名,如果剩下的列全部都要轉換,就不用寫了。# var_name和value_name是自定義設置對應的列名。重新得到的數據如下,新增了date一列,記錄時間。還需要把date列轉換成datetime格式的數據
confirmed['date_dt'] = pd.to_datetime(confirmed.date, format="%m/%d/%y")confirmed.date = confirmed.date_dt.dt.dateconfirmed.rename(columns={'Country/Region': 'country', 'Province/State': 'province'}, inplace=True)

recovered = recovered.melt(id_vars = ['Province/State', 'Country/Region', 'Lat', 'Long'], var_name='date',value_name = 'recovered')recovered['date_dt'] = pd.to_datetime(recovered.date, format="%m/%d/%y")recovered.date = recovered.date_dt.dt.daterecovered.rename(columns={'Country/Region': 'country', 'Province/State': 'province'}, inplace=True)

deaths = deaths.melt(id_vars = ['Province/State', 'Country/Region', 'Lat', 'Long'], var_name='date', value_name = 'deaths')deaths['date_dt'] = pd.to_datetime(deaths.date, format="%m/%d/%y")deaths.date = deaths.date_dt.dt.datedeaths.rename(columns={'Country/Region': 'country', 'Province/State': 'province'}, inplace=True)

現在三種數據都有了,我們把它們合併在一張表裡面,主要用到merge函數
merge_on = ['province', 'country', 'date']all_date = confirmed.merge(deaths[merge_on + ['deaths']], how='left', on=merge_on). \                        merge(recovered[merge_on + ['recovered']], how='left', on=merge_on)

由於要演示的是疫情擴散地圖,因此筆者用實心圓來表示每個地區的疫情變化,而實心圓的大小則代表了三種數據的大小,所以在我們的數據裡要加一列,使用confirmed數據的二分之一次方來表示實心圓的大小。
Coronavirus_map = all_data.groupby(['date_dt', 'province'])['confirmed', 'deaths','recovered', 'Lat', 'Long'].max().reset_index()Coronavirus_map['size'] = Coronavirus_map.confirmed.pow(0.5)  Coronavirus_map['date_dt'] = Coronavirus_map['date_dt'].dt.strftime('%Y-%m-%d')

最後就是繪圖部分,代碼也很簡單,如果有不懂得參數可以使用help(px.scatter_geo)來查看每個參數用法
fig = px.scatter_geo(Coronavirus_map, lat='Lat', lon='Long', scope='asia',                     color="size", size='size', hover_name='province',                     hover_data=['confirmed', 'deaths', 'recovered'],                     projection="natural earth",animation_frame="date_dt",title='亞洲地區疫情擴散圖')fig.update(layout_coloraxis_showscale=False)fig.show()

好了地圖部分就畫好了,代碼運行玩就會出現下面的樣式,點擊播放按鈕,就會動態變化下面是動態演示,展示了從2020-01-21至2020-02-26的疫情擴散情況。

好了,本文到這裡就結束了,希望這次疫情也能早早結束,中國加油!人類加油!

━━━━━━━━━━━━━━━━━━━━

文字來源|木子偉

圖片來源|木子偉

推文編輯|宋欣蕊

推文審核|木子偉

歡迎投稿至:Datahelpclub@126.com

━━━━━━━━━━━━━━━━━━━━

文章好看在這裡

相關焦點

  • 新田抗「疫」在農村|東山村:戰「疫」一線最美「父子兵」
    「作為一名共產黨員,關鍵時刻就得衝鋒在前,堅守一線,誓與新型冠狀病毒肺炎疫情決戰到底。」新田縣陶嶺鎮東山村後備幹部鄭坤鏗鏘有力的說道。  為全面打贏肺炎防控狙擊戰,自1月26日以來,鄭坤每天堅守在防疫一線,除了做好每日防疫執勤工作外,其他時間則開著自己的私家車用車載廣播播放疫情防控知識宣傳,從早上到夜幕來回的穿梭在村頭巷口。
  • 攜手抗擊疫情,守護人類光明!陳奕迅蔡依林合唱抗疫公益MV《Fight as ONE》(共同體的戰鬥)
    疫情沒有國界,病毒不分種族,新冠肺炎疫情的全球蔓延,讓「地球村」每個成員前所未有地意識到,我們的呼吸是如此息息相關,我們的命運是如此緊緊相連。據最新統計數據,全球新冠肺炎確診人數超過百萬,疫情防控全球阻擊戰進入了更加嚴峻的階段。       寒夜裡唯有添薪取暖,方能保護共同的家園。駭浪中唯有同舟共濟,才可抵達希望的彼岸。
  • 好劇推薦:《在一起》——2020良心抗疫劇
    《在一起》這部國產抗疫劇,講述在抗擊疫情期間各行各業平凡人物的真實故事。二十集十個故事,一部真實的抗疫英雄圖鑑,其中有《生命的拐點》《擺渡人》《同行》《救護者》《搜索24小時》《火神山》《方艙》《我叫大連》《口罩》《武漢人》,十個故事演繹大愛中國的抗疫之旅,致敬每一位白衣天使和各行各業逆行者。接下來就讓我們分層次來了解一下這部劇。
  • 榜樣 | 抗「疫」戰「貧」路上的一朵馬蘭菊
    今年春節,一場突如其來的疫情防控阻擊戰驟然打響。疫情就是命令,抗疫就是責任。在相公鎮柳泉村時常會看到一位穿著藍色制服棉襖的女青年,她就是全鎮唯一在抗疫戰線上的巾幗女書記——相公鎮柳泉村駐村第一書記、縣文化和旅遊局幹部賈經鷹。
  • 【眾志成城 抗擊疫情】戰「疫」一線 疾風勁草
    疫情就是命令,防控就是責任。就眼下而言,管住人,管好人是打贏疫情防控阻擊戰第一道關。連日來,堅持不懈的努力,我縣已完成對重點小區、重點人口第一輪排查工作。一線,他們用堅持築起「護城河」;用忠誠當好百姓的「守護人」,他們是戰「疫」一線的疾風勁草。  戰「疫」一線,疾風勁草用行動踐行著初心。認識和評價一個黨員幹部,不僅要看他怎麼說,更要看他怎麼做;不僅要看他平時的言行,更要看他關鍵時刻的表現。歲寒知松柏,危難見道義。逆風而行,無怨無悔,不分晝夜,嚴防死守,他們用行動為初心做了最好的注釋。
  • 致敬最美抗疫戰士,天森人!
    圖片來源:河北抗疫vlog疫情冷酷,人間有愛。1月6日,在大多數人響應政府號召,居家準備接受核酸檢測的同時,河北天森藥業集團的勇士們卻投入到防疫工作的前線中去。大疫面前,逆流而上,勇往直前!◆新中社區衛生服務站,投身核酸檢測一線石家莊市橋西區新中社區衛生服務站,所有的員工全部上崗,打破原有的上班時間,24小時為周邊的小區居民們進行核酸檢測。
  • 發達國家哄搶防疫物資,為使發展中國家獲利,紐西蘭呼籲抗疫物資免稅
    親,閱讀本文前,請您先點擊上面的藍色字體「卡嘴美食世界」,再點擊「關注」,這樣您就可以繼續免費收到每天分享的精彩文章了,好文章我們齊分享
  • 晉州公安:退伍不褪色 抗疫展風採
    晉州公安:退伍不褪色 抗疫展風採 2021-01-16 09:21 來源:澎湃新聞·澎湃號·政務
  • 戴「孝」抗「疫」的逆行者
    戴「孝」抗「疫」的逆行者——青年黨員一線抗擊疫情側記
  • 白玉粉講述援鄂抗「疫」:想把最美好的都給他們
    4月7日,在完成援鄂抗「疫」任務後,抗「疫」英雄白玉粉回到馬關,我們的記者也第一時間對白玉粉進行了採訪,下面我們一起來聽聽英雄白玉粉親口講述援鄂抗「疫」的感動瞬間。抗「疫」英雄白玉粉在馬關人民的期盼中回到了家鄉馬關,迎接的市民、同行、同事都將最美的鮮花和掌聲送給了這位抗「疫」戰士。
  • 黃修平:病倒在抗「疫」一線的大堝村村委會主任
    2月14日下午,塘湖鎮大堝村傳來令人心痛的消息:村委會主任黃修平同志因連日抗疫疲勞過度,在抗疫一線突然陷入昏迷,經縣人民醫院確診為腦血管破裂
  • 永豐抗「疫」:「全家總動員」
    這個春節,本該是很多家庭團聚歡樂的時候,不過,突如其來的新型冠狀病毒感染肺炎疫情改變了一切,在永豐鄉抗擊疫情一線中,有不少人在疫情面前舍小家為大家
  • 新婚第二天 98年的他毅然奔赴抗「疫」一線
    抗「疫」勇挑重擔,青春不負韶華。疫情來襲,無數遼寧青年挺身而出,用實際行動竭盡全力為抗擊疫情做出自己的貢獻。
  • 河北石家莊長安區:線上線下齊動員 抗疫彰顯檢察藍
    河北石家莊長安區:線上線下齊動員 抗疫彰顯檢察藍 2021-01-18 08:00 來源:澎湃新聞·澎湃號·政務
  • 抗「疫」戰場上的金剛戰士
    抗「疫」戰場上的金剛戰士「不吃飯也不顯餓,不睡覺也不顯困」,這是疫情在我市發生後,市應急管理局書記劉東徵此刻的感受。因為忙碌,每天只能睡三四個小時,而這樣的狀態已經持續了十八天了。眼前的他,雙眼布滿血絲,卻依然鬥志昂揚。「我們局承擔著全市疫情防控物資保障的重任,事關全市抗疫大局,不能有絲毫的鬆懈」!他是這樣要求的,更是這樣做的。
  • 《紐時》反思美抗疫:被錯失的一個月......
    幾天後,高福又致電雷德菲爾德,再次誠懇強調了疫情的嚴重性。雷德菲爾德在元旦前後就從中方處知道病毒的嚴重性(法新社)報道指,在中國科學家公開病毒的基因序列兩周後,美國疾控中心開發出檢測工具,但就在美國食品藥物管理局(FDA)批准並交給衛生部門實驗室使用時,在實務操作上發生了結果不一致的混淆狀況,檢測工作被迫停止。
  • 【抗疫記事(35)】 劉定成:「南徵北戰」抗疫路
    後來板橋小學老師蘇曉成看到大家太辛苦,主動提出中午值守(按照文件精神,參加線上教學的老師可以不參加疫情防控);從北京回老家探親的志願者石波主動提出,參加夜班值守;後來陸續又有部分志願者不斷加入,大家的防控壓力略有緩解。
  • 世界紅十字日 || 亨利·杜南是誰?
    你是否也和團小白有著一樣的疑惑不知道亨利·杜南是誰接下來團小醫就帶你來認識一下這位偉大的老爺爺一位不可不知的偉大人物,開闢了一項譽滿全球、造福全人類的偉大事業。每年的5月8日是國際紅十字日。近半個世紀以來,每到這一天,全世界崇尚人道主義的人都在紀念一位感動全人類並改變人類歷史的偉大人物--國際紅十字運動之父亨利·杜南。
  • 暖心奶茶送抗「疫」戰士 暖身又暖心
    自河北省新冠肺炎疫情發生以來,新花園社區的黨員、群眾、大學生志願者積極響應號召、挺身而出,踴躍參與到疫情防控工作中,構築起疫情防控的堅強堡壘,他們在值守崗位上勸返外來人員,發放通行證,為居民們測溫掃碼登記,和在一線英勇奮鬥的廣大疫情防控人員一道
  • 世葉總會2020年助力抗「疫」捐款捐物通告
    抗擊疫情,葉氏大愛。自從世葉總會先後向總會領導成員和廣大宗親,兩次發出捐款捐物、支援抗疫《倡議書》以來,得到了總會人領導成員的響應,在短期內捐集到百萬元及時委託祖地葉縣黨政將我們的捐款投入到抗疫救災中。此後,不少宗親積極響應,到2月20日止,已有近350人捐款(還在續捐),共捐得人民幣應在140萬元左右。這些捐款都將委託祖地按國家規定捐到抗疫前線去。