116 11 个案例掌握 Python 数据可视化--遥遥无期的美国新冠疫情

遥遥无期的美国新冠疫情

新型冠状病毒引发的全球疫情是 2020 年度最有影响力的事件之一,本实验获取了美国健康统计中心 (National Center for Health Statistics,NCHS),纽约时报(nytimes)等多个数据集,对美国新冠疫情做了分析,研究及可视化了疫情发展及其对餐饮业的影响。
输入并执行魔法命令 %matplotlib inline, 去除所有图右侧、顶部、图例边框。

%matplotlib inline
import matplotlib.pyplot as plt
import warnings

plt.rcParams['axes.spines.bottom']=True
plt.rcParams['axes.spines.left']=True
plt.rcParams['axes.spines.right']=False
plt.rcParams['axes.spines.top']=False
plt.rcParams['legend.frameon']=False
warnings.filterwarnings("ignore") # 屏蔽报警

纽约时报疫情数据集介绍

本数据集来自纽约时报对美国各个州及乡镇新冠疫情确诊人数和死亡人数的按日统计。
导入数据,并进行以下初步处理:将日期列转为日期格式,根据日期进行确诊人数、死亡人数的聚合,查看前 5 行。

import pandas as pd
df = pd.read_csv('https://labfile.oss.aliyuncs.com/courses/3023/US_counties_case_death.csv')
data = df

data['date'] = pd.to_datetime(data['date']).dt.date

data = data.groupby(['date'])['cases', 'deaths'].sum()
data.head()

确诊及死亡人数变化趋势

!pip install pyecharts==1.7.1

将确诊人数和死亡人数按日绘制折线图,观察各日期阶段的变化趋势。趋势类可视化是大多数问题研究的第一步,通常采用的是折线图,但多数情况下会遇到以下问题:
日期等时间序列数据,往往日期数很多,当绘制到一张图上,数据非常紧凑,难以看到某一阶段的细节。
需要可视化的序列往往量纲不一致,当绘制到一张图上时,由于量纲的问题,有些系列往往无法有效显示。

相比于 Matplotlib , Pyecharts 包更适宜这类问题的可视化。Pyecharts 提供了数据尺度缩放的参数设置 datazoom_opts ,让紧凑的 x 轴可以在一定时间尺度范围内滑动调节,读者可根据需要查看某一时期数据的细节,另一方面提供了副坐标 extend_axis, 使量纲不同的序列均能在坐标轴上较好的展示。

import pyecharts.options as opts
from pyecharts.charts import Line
import matplotlib.colors as cs

line = Line()
# 主坐标数据添加
line.add_xaxis(xaxis_data=data.index)
line.add_yaxis(
    series_name="cases",
    y_axis=data['cases'],
    symbol="emptyCircle",
    yaxis_index=0,
    is_symbol_show=True,
    color=cs.TABLEAU_COLORS['tab:blue'],
    label_opts=opts.LabelOpts(is_show=False),
    linestyle_opts=opts.LineStyleOpts(width=6),
)

# 次坐标数据添加
line.add_yaxis(
    series_name="deaths",
    y_axis=data['deaths'],
    symbol="emptyCircle",
    yaxis_index=1,
    is_symbol_show=True,
    color=cs.TABLEAU_COLORS['tab:red'],
    linestyle_opts=opts.LineStyleOpts(width=6),
    label_opts=opts.LabelOpts(is_show=False),
)
# 次坐标设置
line.extend_axis(
    # x数据
    xaxis_data=data.index,
    # 次坐标轴,主要是y轴的设置
    yaxis=opts.AxisOpts(
        type_="value",
        name="deaths",
        name_textstyle_opts=opts.LabelOpts(font_size=18,),
        axislabel_opts=opts.LabelOpts(font_size=15,)
    )
)
# 全局设置(主要为主坐标相关的设置)
line.set_global_opts(
    # 标题相关设置
    title_opts=opts.TitleOpts(
        title="The Cases & Deaths of COVID-19 of The United States of American ",
        pos_left="10%",
        title_textstyle_opts=opts.LabelOpts(font_size=20,)
    ),
    # 图例相关设置
    legend_opts=opts.LegendOpts(
        pos_top="5%",
        textstyle_opts=opts.LabelOpts(font_size=15,)
    ),
    # 数据缩放相关设置,前者为底部缩放条,后者为内部鼠标滚轮缩放选项
    datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(
        type_="inside")],
    # x 轴相关的设置
    xaxis_opts=opts.AxisOpts(
        type_="category",
        axislabel_opts=opts.LabelOpts(font_size=15,)
    ),
    # y 轴相关的设置
    yaxis_opts=opts.AxisOpts(
        type_="value",
        name="cases",
        name_textstyle_opts=opts.LabelOpts(font_size=18,),
        axistick_opts=opts.AxisTickOpts(is_show=True),
        splitline_opts=opts.SplitLineOpts(is_show=True),
        axislabel_opts=opts.LabelOpts(font_size=15,)
    ),
)

line.render_notebook()

拖动图下方的时间条,可以调节查看数据的开始及结束时间;同时可在图内部滑动鼠标滚轮,进行数据的缩放。从运行结果可以看出:
无论是确诊数还是死亡人数,美国的疫情都没有看到一个显著的拐点;
确诊人数(红线)上,斜率分为两个阶段,4 月初开始第一阶段,7 月初开始第二阶段,第二阶段的斜率大于第一阶段;
死亡人数(蓝线)上,斜率分为三个阶段:4 月份开始斜率突然升高,6 月中旬左右稍有降低,后在 8 月出开始了新的上涨,但 8 月斜率比 4 月 稍低;

死亡人数随日期变化可视化

另外一种时间序列可视化的绘图对象是日历热力图,通过传入日期、数据的二维列表对数据进行可视化,由颜色条查询数据的对应关系。本例可视化了死亡人数随日期的变化趋势。

from pyecharts.charts import Calendar

df = pd.read_csv('https://labfile.oss.aliyuncs.com/courses/3023/US_counties_case_death.csv')
data = df

data['date'] = pd.to_datetime(data['date']).dt.date

data = data.groupby(['date'])['deaths'].sum()

# 后一天死亡人数减前一天死亡人数
data = data-data.shift(1)
data = data.fillna(0)

# 生成日历图的数据格式
data = [
    [date, death]
    for date, death in zip(data.index, data)
]

calender = Calendar(init_opts=opts.InitOpts(width='900px', height='300px'))
calender.add(
    "",
    data,
    calendar_opts=opts.CalendarOpts(
        range_="2020",
        monthlabel_opts=opts.LabelOpts(),
    ),
)
calender.set_global_opts(
    title_opts=opts.TitleOpts(
        title="The Deaths of COVID-19 of The United States of American "),
    visualmap_opts=opts.VisualMapOpts(
        max_=2800,
        min_=20,
        split_number=5,
        orient="horizontal",
        range_color=[cs.TABLEAU_COLORS['tab:blue'],
                     cs.TABLEAU_COLORS['tab:red']],
        is_piecewise=True,
        pos_top="230px",
        pos_left="100px",
    ),
)
calender.render_notebook()

从运行结果可以看出:四月份出现了第一波较高的死亡人数,八月份出现了第二波较高的死亡人数

确诊人数随日期变化可视化

同样的方式,得到确诊人数随日期的变化趋势。

df = pd.read_csv('https://labfile.oss.aliyuncs.com/courses/3023/US_counties_case_death.csv')
data = df

data['date'] = pd.to_datetime(data['date']).dt.date

data = data.groupby(['date'])['cases'].sum()

data = data-data.shift(1)
data = data.fillna(0)

data = [
    [date, case]
    for date, case in zip(data.index, data)
]


calender = Calendar(init_opts=opts.InitOpts(width='900px', height='300px'))
calender.add(
    "",
    data,
    calendar_opts=opts.CalendarOpts(
        range_="2020",
        monthlabel_opts=opts.LabelOpts(),
    ),
)
calender.set_global_opts(
    title_opts=opts.TitleOpts(
        title="The Cases of COVID-19 of The United States of American "),
    visualmap_opts=opts.VisualMapOpts(
        max_=76000,
        min_=0,
        split_number=5,
        orient="horizontal",
        range_color=[cs.TABLEAU_COLORS['tab:blue'],
                     cs.TABLEAU_COLORS['tab:red']],
        is_piecewise=True,
        pos_top="230px",
        pos_left="100px",
    ),
)
calender.render_notebook()

从运行结果可以看出,与死亡人数变化趋势相反,七月份引发的第二波确诊人数的数值增长显著性的高于第一波。

美国疾控中心死亡人数统计数据集介绍

美国健康统计中心(NCHS)负责全美各州死亡人数、死亡原因等数据的统计,本数据获取了 2015 年 - 2020 年 10 月 3 日期间美国各管辖区周死亡人数统计数据。本数据集包含以下字段:


image.png

导入数据并查看前 5 行。

df = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/3023/Weekly_deaths_by_jurisdiction_and_race_cleaning.csv')
df.head()

所有原因造成的死亡人数

将死亡人数按照年、周、死亡原因进行聚合,并通过数据透视,得到每年、每周对应各原因的死亡总人数。

df = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/3023/Weekly_deaths_by_jurisdiction_and_race_cleaning.csv')
data = df

data = data.groupby(['MMWRYear', 'MMWRWeek', 'Outcome'],
                    as_index=False)['Number of Deaths'].sum()
# 将multi—index裂解
data = data.pivot_table(values='Number of Deaths',
                        index=['MMWRYear', 'MMWRWeek'],
                        columns='Outcome',
                        aggfunc='sum',
                        )
data['Year'] = data.droplevel(level=1).index
data['Week'] = data.droplevel(level=0).index
data['Year'] = data['Year'].astype('category')
data.head()

折线图有两种绘图方式,第一种是通过基础接口 plt.plot 实现,另一种是通过高级接口 sns.lineplot 实现,相比于基础接口,高级接口需要的数据处理步骤更少。如本例中,只需要一行代码即可实现历年按周死亡人数的可视化,如果通过基础接口实现,则需要遍历每一个年份,再根据工作周进行数据聚合。
另一方面,折线图常与面积填充图 plt.fill_between 共同搭配使用,以实现关键信息地突出显示。如本例通过填充图较好地展示了因为疫情因素,2020 年度前 40 个工作周相比历年同时段额外死亡的人数。

import seaborn as sns
import numpy as np
fontsize = 17
plt.rcParams['xtick.labelsize'] = fontsize
plt.rcParams['ytick.labelsize'] = fontsize
plt.rcParams['axes.labelsize'] = fontsize
plt.rcParams['axes.titlesize'] = fontsize
plt.rcParams['legend.fontsize'] = fontsize
plt.rcParams['legend.title_fontsize'] = fontsize


plt.rcParams['figure.figsize'] = (15, 6)
# 绘制历年 周死亡人数
sns.lineplot(x='Week', y='All Cause', hue='Year',
             data=data, palette='Blues', lw=4)

# 前40周,标注2020年比2019年超死亡人数
week_num = 40
where = np.array(data.loc[data['Year'] == 2020, 'All Cause'][:week_num]) > np.array(
    data.loc[data['Year'] == 2019, 'All Cause'][:week_num])
plt.fill_between(data.loc[data['Year'] == 2020, 'Week'][:week_num],
                 data.loc[data['Year'] == 2020, 'All Cause'][:week_num],
                 data.loc[data['Year'] == 2019, 'All Cause'][:week_num],
                 where=where,
                 color='tab:red',
                 alpha=0.6,
                 label='Excess Death'
                 )

# 添加备注
comment = '* Data in recent weeks are incomplete. \n* Only 60% of death records are submitted to NCHS within 10 days of the date of death\n  and completeness varies by jurisdiction.'
ax = plt.gca()
ax.text(0.01, 0.05, comment, va='bottom', transform=ax.transAxes, fontsize=17)

plt.legend(loc=1)
plt.ylabel('Death Cause by All Reason')
plt.title('Dead Population by All Cause Per Week of The United States of American')

从运行结果可知:
2020 年度以前,美国历年死亡人数随工作周大致有相同的分布规律;
2020 年度,由于新冠疫情因素,死亡人数较 2019 年有了显著增长;
由新冠疫情带来的额外死亡人数分为两个明显的峰,第一个峰的死亡人数远大于第二个峰;
2020 年度 38 周以后死亡人数迅速下降,原因是由于 NCHS 未能及时获得该工作周完全的统计数据(原因解释见图左下角标注文字)。

新冠造成的死亡人数

同样的方式,可视化新冠疫情导致的死亡人数。

fontsize = 17
plt.rcParams['xtick.labelsize'] = fontsize
plt.rcParams['ytick.labelsize'] = fontsize
plt.rcParams['axes.labelsize'] = fontsize
plt.rcParams['axes.titlesize'] = fontsize
plt.rcParams['legend.fontsize'] = fontsize
plt.rcParams['legend.title_fontsize'] = fontsize
plt.rcParams['figure.figsize'] = (12, 5)


sns.lineplot(x='Week', y='COVID-19', hue='Year',
             palette='Blues', legend=False, lw=6, data=data)

week_num = 40
plt.fill_between(data.loc[data['Year'] == 2020, 'Week'][:week_num],
                 data.loc[data['Year'] == 2020, 'COVID-19'][:week_num],
                 0,
                 color='tab:red',
                 alpha=0.6,
                 label='Excess Death'
                 )
plt.legend()
plt.ylabel('Death Cause by COVID-19')

plt.title(
    'Dead Population Per Week by COVID-19 of The United States of American', fontsize=20)

从运行结果可以看出,本例与实验 2.6 的结论相同,不同的是,本例将历年的基线调整为 0, 对各个峰值的相对以及绝对数据的可视化更为清晰。

各州死亡人数增长率

选取 2019 和 2020 年度的死亡人数数据,并通过求差获得 2020 年度死亡人数增长率。

df = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/3023/Weekly_deaths_by_jurisdiction_and_race_cleaning.csv')
data = df

# 选择2019和2020年数据
data = data.loc[(data['MMWRYear'] == 2019) | (data['MMWRYear'] == 2020)]
# 选择前37周数据
data = data.loc[data['MMWRWeek'] <= 37]
# 选择所有死亡人数
data = data.loc[data['Outcome'] == 'All Cause']

data = data.groupby(['Jurisdiction', 'MMWRWeek', 'MMWRYear'],
                    as_index=False)['Number of Deaths'].sum()
# # 将multi—index裂解
data = data.pivot_table(values='Number of Deaths',
                        index=['Jurisdiction', 'MMWRWeek'],
                        columns='MMWRYear',
                        aggfunc='sum',
                        )
data['States'] = data.droplevel(level=1).index
data['Week'] = data.droplevel(level=0).index
data['Year_increase /%'] = 100*(data[2020]-data[2019])/data[2019]
data

将全美各州死亡率变化趋势分别绘制成子图,并在子图中添加全美平均线。

fontsize = 15
plt.rcParams['xtick.labelsize'] = fontsize
plt.rcParams['ytick.labelsize'] = fontsize
plt.rcParams['axes.labelsize'] = fontsize
plt.rcParams['axes.titlesize'] = fontsize
plt.rcParams['legend.fontsize'] = fontsize
plt.rcParams['legend.title_fontsize'] = fontsize

# 各州按总死亡率进行降序排列
states = data.groupby(['States'])['Year_increase /%'].sum(
).sort_values(ascending=False).index

fig = plt.figure(figsize=(22, 10))

nrows = 6
ncols = 9

# 全美平均线
avg = data['Year_increase /%'].mean()

for i, state in enumerate(states):
    ax = fig.add_subplot(nrows, ncols, i+1)

    # 获取各州数据
    state_data = data.loc[data['States'] == state]

    # 绘制全美平均增长率
    ax.axhline(y=avg, color='tab:red', lw=3, alpha=0.6, ls='--')

    # 绘制各州每周增长率
    ax.plot('Week', 'Year_increase /%',
            data=state_data,
            color='tab:blue',
            alpha=0.8,
            lw=4)

    # 标注平均周增长率
    mean_increase = state_data['Year_increase /%'].mean()
    ax.text(0.9, 0.9,
            '%.1f%%' % mean_increase,
            transform=ax.transAxes,
            fontsize=15,
            va='center',
            ha='center',
            bbox={'facecolor': 'tab:orange',
                  'boxstyle': 'round',
                  'alpha': 0.2}
            )

    ax.set_title(state)
    ax.set_ylim((-20, 80))

    if (i % ncols) != 0:
        ax.set_yticks([])
    else:
        ax.set_ylabel('Increase/%',fontsize=14)
        ax.set_yticks([-10,20,60])

    if i < (nrows-1)*ncols:
        ax.set_xticks([])
    else:
        ax.set_xticks(np.arange(0, 38, 9))
        ax.set_xlabel('Week')


fig.suptitle('Dead Population Increase Compared to 2019 of The United States of American',
             fontsize=20, va='top')
plt.subplots_adjust(wspace=0.1, hspace=0.3)

从运行结果可知:
53个辖区,年度平均增长率约为 11.78% ( avg 的数值),有 21 个辖区高于平均增长率;
纽约州城区、新泽西州第一波涨幅惊人达到了 100% 以上;
全美疫情的两波死亡人数增长,第一波主要由纽约等州构成,第二波主要由德克萨斯等州构成;
相当一部分州在第一波疫情后,第二波未再出现明显的死亡人数增长;
华盛顿等增长率排名靠后的州,没有出现明显的的死亡率峰。

各种族死亡人数增长率

将各种族的数据进行死亡人数增长率的计算。

df = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/3023/Weekly_deaths_by_jurisdiction_and_race_cleaning.csv')
data = df

data = data.loc[(data['MMWRYear'] == 2019) | (data['MMWRYear'] == 2020)]

data = data.loc[data['MMWRWeek'] <= 37]

data = data.loc[data['Outcome'] == 'All Cause']

data = data.groupby(['Race/Ethnicity', 'MMWRWeek', 'MMWRYear'],
                    as_index=False)['Number of Deaths'].sum()

data = data.pivot_table(values='Number of Deaths',
                        index=['Race/Ethnicity', 'MMWRWeek'],
                        columns='MMWRYear',
                        aggfunc='sum',
                        )
data['Races'] = data.droplevel(level=1).index
data['Week'] = data.droplevel(level=0).index
data['Year_increase /%'] = 100*(data[2020]-data[2019])/data[2019]
data

将各种族死亡率变化趋势与全美死亡率变化趋势进行分面绘制。

fontsize = 17
plt.rcParams['xtick.labelsize'] = fontsize
plt.rcParams['ytick.labelsize'] = fontsize
plt.rcParams['axes.labelsize'] = fontsize
plt.rcParams['axes.titlesize'] = fontsize
plt.rcParams['legend.fontsize'] = fontsize
plt.rcParams['legend.title_fontsize'] = fontsize
plt.rcParams['figure.figsize'] = (20, 7)

fig, axs = plt.subplots(2, 3, sharex=True)

races = data.groupby('Races')['Year_increase /%'].mean().sort_values().index

axs = axs.ravel()
for i, race in enumerate(races):
    ax = axs[i]
    race_data = data.loc[data['Races'] == race]
    ax.plot(race_data['Week'], race_data['Year_increase /%'], lw=4)
    ax.set_title(race)

    ax.fill_between(
        race_data['Week'], race_data['Year_increase /%'], color='tab:red', alpha=0.7)

    # 标注平均周增长率
    mean_increase = race_data['Year_increase /%'].mean()
    ax.text(0.9, 0.8,
            '%.1f%%' % mean_increase,
            transform=ax.transAxes,
            fontsize=15,
            va='center',
            ha='center',
            bbox={'facecolor': 'tab:blue',
                  'boxstyle': 'round',
                  'alpha': 0.2}
            )
    
    # 绘制全美国趋势
    sns.lineplot(x='Week', y='Year_increase /%', color='k',
                 err_style='bars', err_kws={'lw': 0},  # 误差样式选用误差线,并将误差线线宽置为0,则不显示误差线
                 data=data, alpha=0.7, lw=4, label='Avg of USA', ax=ax)

    ax.legend(loc=2, fontsize=15)
fig.suptitle('Dead Population Increase Compared to 2019 of The United States of American',
             fontsize=20, va='top')

从运行结果可知,非西班牙裔白人平均增长死亡率最低为 8.2%, 后续依次是亚裔、黑人、本地土著、西班牙裔,数据中包含没有种族记录的死者信息,该部分人员平均增长死亡率最高为 44.3% 。

各年龄层死亡人数增长率

数据集介绍:
NCHS 同时发布了全美各州各年龄层死亡人数数据的统计,通过以下过程获得各年龄层死亡增长率数据。

df = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/3023/Weekly_deaths_by_jurisdiction_and_age_clearning.csv')

data = df

data = data.loc[(data['Year'] == 2019) | (data['Year'] == 2020)]

data = data.loc[data['Week'] <= 37]

data = data.groupby(['Age Group', 'Week', 'Year'],
                    as_index=False)['Number of Deaths'].sum()
# 将multi—index裂解
data = data.pivot_table(values='Number of Deaths',
                        index=['Age Group', 'Week'],
                        columns='Year',
                        aggfunc='sum',
                        )
data['Ages'] = data.droplevel(level=1).index
data['Week'] = data.droplevel(level=0).index
data['Year_increase /%'] = 100*(data[2020]-data[2019])/data[2019]
data

通过 sns.lineplot 接口可以快速进行各年龄层的可视化,需要注意的是:
sns.lineplot 接口的 palette 颜色板与 hue 序列是一一对应的;
对于非数字的 hue ,sns.lineplot 接口的排序方式是根据 hash 值,因此当默认排序不符合制图要求时,可通过传入 hue_order 进行修正。

fontsize = 20
plt.rcParams['xtick.labelsize'] = fontsize
plt.rcParams['ytick.labelsize'] = fontsize
plt.rcParams['axes.labelsize'] = fontsize
plt.rcParams['axes.titlesize'] = fontsize
plt.rcParams['legend.fontsize'] = fontsize
plt.rcParams['legend.title_fontsize'] = fontsize
plt.rcParams['legend.fontsize'] = 17

plt.rcParams['figure.figsize'] = (15, 6)

# Age_group 排序
hue_order = ['Under 25 years', '25-44 years', '45-64 years', '65-74 years', '75-84 years',
         '85 years and older', ]

sns.lineplot(x='Week', y='Year_increase /%', hue='Ages',hue_order=hue_order,
             palette='Blues', data=data, lw=4)
plt.title('Dead Population Increase Compared to 2019 of The United States of American',
          fontsize=20, va='top')

从运行结果可知,相比于 25 岁以下年龄组,65 岁以上年龄组有着较高的死亡增长率,且 65 - 74,75 - 84,85 以上三组未表现出较为明显的差异。

搜索引擎疫情响应关键词检索情况

2003 年非典期间,据传 Google 搜索平台早于中国大陆获得了 SARS 爆发的情报,请原理是通过互联网相关关键词搜索请求词频变化规律的分析。针对本次疫情,Google 开放了其相关疾病关键词检索词频的日数据。
导入清洗后数据,清洗数据主要是获得相关性较高的词频统计数据,相关性较高的单词包括:


image.png
df = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/3023/2020_US_daily_symptoms_dataset_cleaning.csv')
data = df

data.head().T

将相关关键词的时间变化趋势可视化。此处绘制了渐变色风格的填充图,其原理是:
通过 plt.imshow 接口将子图通过 2 * 2 的列表数据及渐变色色板 plt.cm.Blues 进行填充;
绘制折线图;
将折线图上部通过 plt.fill_between 接口进行纯色填充。

fontsize = 17
plt.rcParams['xtick.labelsize'] = fontsize
plt.rcParams['ytick.labelsize'] = fontsize
plt.rcParams['axes.labelsize'] = fontsize
plt.rcParams['axes.titlesize'] = fontsize
plt.rcParams['legend.fontsize'] = fontsize
plt.rcParams['figure.figsize'] = (18, 10)

symptoms = [
    'symptom:Asthma',  # 哮喘
    'symptom:Common cold',  # 感冒
    'symptom:Hay fever',  # 枯草发烧
    'symptom:Headache',  # 头痛
    'symptom:Fever',  # 发烧
    'symptom:Low-grade fever'  # 低烧
]

fig, axs = plt.subplots(3, 2)

axs = axs.ravel()

for i, symptom in enumerate(symptoms):
    ax = axs[i]

    # 绘制各关键词每周词频变化趋势图
    week_data = data.groupby(['week'])[symptom].sum()
    ax.plot(week_data.index, week_data, color='k', lw=5)

    # 将整张图用渐变色背景进行填充
    xlim = xmin, xmax = week_data.index.min(), week_data.index.max() # 获取图x轴范围
    ylim = ymin, ymax = week_data.min(), week_data.max() # 获取图y轴范围
    ax.imshow(X=[[100, 100], [0, 0]], # 将整张图分为 4 个数值区间,顶部是100,底部是0
              cmap=plt.cm.Blues,  # 将所有数值通过Blues颜色板进行配色
              norm=None,
              extent=(xmin, xmax, ymin, ymax), # 扩展到整张图
              aspect='auto',
              interpolation='bicubic', # 处于数据区间内部的小单元格插值方法
              vmin=1,
              vmax=120,)

    # 将上部分的区域用fill白色填充
    ax.fill_between(x=week_data.index, y1=week_data,
                    y2=week_data.max(), color='#FFFBFF')

    # 简单修饰
    ax.set_title(symptom.split(':')[1])
    ax.set_ylabel('Search Times')
    if i >= 4:
        ax.set_xlabel('Week')

plt.subplots_adjust(wspace=0.2, hspace=0.3)
fig.suptitle('Daily Search Symptoms Trend by Google of The United States of American',
             fontsize=20, va='top')

从运行结果可知:
感冒(Common cold),发烧(Fever)的搜索词频峰值最高;
感冒,发烧,风热发烧(Hay fever)等关键词在第 10 周搜索词频显著增加,这与全美死亡率增长曲线的拐点几乎一致;
遗憾的是,Google 词频似乎没有做到较为明显的领先优势,只是基本保持了同步。

疫情后的经济复苏还要多久-以餐饮业为例

餐厅上座率数据集介绍
OpenTable 发布了 2020 年度美国主要州餐饮入座率相比上年度同期的变化情况,将数据简单处理并查看前 5 行。

df = pd.read_csv('https://labfile.oss.aliyuncs.com/courses/3023/Seated_diner_data.csv')
df = df.loc[df['Type'] == 'state']

# 宽数据变为长数据
df = df.melt(id_vars=['Type', 'Name'], value_name='Seated Percent',)
df = df.rename(columns={'variable': 'Date'})

df['Date'] = pd.to_datetime(df['Date']).dt.date

df.head()

全美
sns.lineplot 接口在绘制折线图的同时,同时对每个位置进行 95% 置信区间的参数估计,并以误差线或者误差带(通过参数 err_style 调节,默认是误差带)的形式可视化,本例可视化了 2020 年度 2 月 18 日 - 9 月 29 日期间全美日均餐厅入座率下降情况,并以误差的形式展示了其 95% 置信区间。

from datetime import date

fontsize = 20
plt.rcParams['xtick.labelsize'] = fontsize
plt.rcParams['ytick.labelsize'] = fontsize
plt.rcParams['axes.labelsize'] = fontsize
plt.rcParams['axes.titlesize'] = fontsize
plt.rcParams['legend.fontsize'] = fontsize


fig, ax = plt.subplots(1, 1, figsize=(10, 6))
sns.lineplot(x='Date', y='Seated Percent', legend=False,
             alpha=0.4, lw=4, data=df, ax=ax)

# 设置 x 刻度
start_date = date(2020, 2, 19)
mid_date1 = date(2020, 5, 5)
mid_date2 = date(2020, 6, 20)
end_date = date(2020, 9, 29)

plt.xticks([start_date, mid_date1, mid_date2, end_date],
           ['Feb/18', 'May/5', 'Jun/20', 'Sep/29'])
plt.xlim(start_date, end_date)

# 设置 y 刻度
plt.yticks([-95,   -80, -60, -40, 0,    10, 40],
           ['-95%', '', '', '-40%', 0, '+10%', ''])
plt.ylim(-100, 25)

plt.axhline(y=0, color='darkred', lw=3, ls='--')
plt.xlabel('')
plt.title('The Seated Percent Compared to Last Year by COV-19 of USA')

从运行结果可知:
伴随着第一波疫情,餐厅入座率迅速降低 100% ;
5 月 5 日左右,全美餐饮业开始复苏,出现了就座率上升的拐点;
截止 9 月底,全美餐饮就座率仍较上年度降低了 40%,且未出现较为明显且强劲的上升趋势。
弗罗里达州和加州
本例可视化了全美各州的餐饮业就座率变化趋势(灰度显示),并将弗罗里达和加州两州的数据用彩色进行了突出显示。

fontsize = 20
plt.rcParams['xtick.labelsize'] = fontsize
plt.rcParams['ytick.labelsize'] = fontsize
plt.rcParams['axes.labelsize'] = fontsize
plt.rcParams['axes.titlesize'] = fontsize
plt.rcParams['legend.fontsize'] = fontsize

show_states = ['California', 'Florida']
colors = ['tab:blue', 'tab:red']

fig, ax = plt.subplots(1, 1, figsize=(12, 6))
hue_order = df.groupby(['Name'])['Seated Percent'].mean().sort_values().index
sns.lineplot(x='Date',
             y='Seated Percent',
             hue='Name',
             hue_order=hue_order,
             legend=False,
             palette='gray',
             alpha=0.4,
             data=df, ax=ax)
for i, show_state in enumerate(show_states):
    plt.plot(df.loc[df['Name'] == show_state, 'Date'],
             df.loc[df['Name'] == show_state, 'Seated Percent'],
             lw=3,
             label=show_state,
             color=colors[i])

# 设置 x 刻度
start_date = date(2020, 2, 19)
mid_date1 = date(2020, 5, 5)
mid_date2 = date(2020, 6, 20)
end_date = date(2020, 9, 29)

plt.xticks([start_date, mid_date1, mid_date2, end_date],
           ['Feb/18', 'May/5', 'Jun/20', 'Sep/29'])
plt.xlim(start_date, end_date)

# 设置 y 刻度
plt.yticks([-95,   -80, -60, -40, 0,    10, 40],
           ['-95%', '', '', '-40%', 0, '+10%', '+40%'])
plt.ylim(-100, 80)

plt.axhline(y=0, color='darkred', lw=3, ls='--')
plt.xlabel('')
plt.title('The Seated Percent Compared to Last Year by COV-19 of USA')
plt.legend()
plt.show()

从运行结果可知,弗罗里达和加州都受到了疫情影响,相比于加州,弗罗里达餐饮业恢复较快。

你可能感兴趣的:(116 11 个案例掌握 Python 数据可视化--遥遥无期的美国新冠疫情)