从Marplotlib到Plotly: 教你入门Python数据可视化

从Marplotlib到Plotly: 教你入门Python数据可视化

作为一名数据科学家,在了解 Plotly 之前,我曾经非常依赖 Matplotlib 完成我的数据可视化任务。

虽然 Matplotlib 是在 Python 中创建可视化最快且最直接的工具,但它最适合初始的探索性分析和静态绘图。如果你想通过 Matplotlib 制作基本静态图以外的东西,需要进行非常复杂的操作。

另一方面,Plotly 是一个较新的开源图形库,可以高效地创建更复杂的交互式可视化。操作也很简单,只需几行代码就能创建美观的交互式绘图。近年来,Plotly在数据科学界非常受欢迎,用的人也越来越多,未来可能会超过 Matplotlib 的人气。

本文将逐步带领你通过 Plotly 创建带有自定义工具框(Customized Tooltips)范围滑(Range Slider)交互式组合图(Interactive Combo Chart)。在本教程中,你将学习Plotly的关键概念和特性,文章也会为您提供完整的代码。如果你想了解更多数据分析相关内容,可以阅读以下这些文章:
数据可视化Data Visualization需要哪些图表技能?
数据科学必备技能:如何用Power BI做数据可视化
用漏斗可视化,讲好数据故事
数据可视化干货:如何为你的Data Visualization找到正确的色板?

我们构建的交互式组合图如下所示:

通过 Plotly 构建的交互式组合图(图片由作者提供)

Plotly Express Vs. Plotly Go

Python的Plotly库是一个交互式开源图形库,涵盖了多种图表类型和数据可视化用例。Plotly Python有一个 Plotly Express 包装器,是 Plotly 的高级接口。

Plotly Express 可以通过简单的语法,快速创建最常见图形的原型,但对于高级图表或自定义图表来说,缺乏功能性和灵活性。

与 Plotly Express 相比,Plotly Go(图形对象)是一个较低级别的图形包,通常需要更多编程,但可自定义,且灵活性更强。在本教程中,我们将通过 Plotly Go 创建如上所示的组合图。你还可以将代码保存为模板,用于在其他用例中创建类似的图表。

下载数据

我们用来创建图表的数据可以从 CDC 网站下载。这是一个开放数据集,用于记录美国每日 Covid-19 新增病例以及 7 天内平均变化量。

https://covid.cdc.gov/covid-data-tracker/#trends_dailycases

每日 Covid-19 病例数据(数据来源:CDC)

导入库(Libraries)并读取数据

首先,导入本教程所需的所有库,并将数据读入 python。如果这是你第一次使用 Plotly,你需要在导入库之前安装 Plotly。你可以在Jupyter笔记本上运行以下命令(我已经安装了 Plotly,所以页面显示“符合要求”)

安装 Plotly(图片由作者提供)
#Import Libraries
import numpy as np
import pandas as pd
import plotly.graph_objects as go
from datetime import datetime

#Read the data
df=pd.read_csv('.../data_table_for_daily_case_trends__the_united_states.csv')
数据集信息(图片由作者提供)

这个数据集相对比较简单,“几乎”可以直接用于可视化。我们注意到“日期(Date)”字段是一个字符串,因此,我们需要将其转换为类型“日期”。此外,为了达到最佳效果,我总是重命名单词之间有空格的字段,因此我们将通过删除空格,重命名最后三个字段。

最后,我们希望在绘图的工具框中显示新增病例”和“7 天内平均变化量”。如果数字以千位分隔符显示,看起来会更直观。我们可以通过创建两个新的重新格式化的字段(对象类型),解决这个问题,这些字段将显示带有千位分隔符的数字。

#Clean and Reformat the Data Fields
df['Date']=df['Date'].str[4:6]+df['Date'].str[:3]+df['Date'].str[7:11]
df['Snapshot_Date'] = pd.to_datetime(df['Date'], format='%d%b%Y').dt.date #Create a new column that has the 'date' type
df = df.rename({'New Cases': 'New_Cases', '7-Day Moving Avg': 'Seven_Day_Avg','Historic Cases':'Historic_Cases'}, axis=1) #Rename the fields
df.loc[:, "New_Cases_formatted"] = df["New_Cases"].map('{:,d}'.format) #Create a new column that shows thousand seperator in numbers (though the new column is now an object not integer)
df.loc[:, "Seven_Day_Avg_formatted"] = df["Seven_Day_Avg"].map('{:,d}'.format) #Create a new column that shows thousand seperator in numbers (though the new column is now an object not integer)
用于可视化的数据框

通过 Plotly Go 创建标准组合图(Standard Combo Chart)

如果想要通过 Plotly Go(图形对象)绘图,我们需要先用 go.Figure() 创建一个图形,然后使用 fig.add_trace() 添加两条迹线(Trace)。什么是迹线?以下定义来自 Plotly 文档:

“迹线是我们给数据集合的名称,以及我们希望绘制数据的规格。请注意,迹线本身也是一个对象,其名称根据你希望数据在绘图表面上的显示方式而定。”

迹线就像你想通过数据绘制的特定可视化类型,数量高达 40 多种,包括散点图、条形图、饼图、等值线图等。在本示例中,由于我们正在绘制组合图(折线图和条形图的组合),我们将添加两条迹线。

fig = go.Figure() #Create a Plotly Graph_Objects Figure
#Add the first trace/bar chart to the figure
fig.add_trace(
    go.Bar(
        x=df['Snapshot_Date'],
        y=df['New_Cases'],
        name="New Cases", 
        marker_line_color='#11457E',
        marker_line_width=2, 
        opacity=0.7)
    )
#Add the second trace/line chart to the figure
fig.add_trace(
    go.Scatter(
        x=df['Snapshot_Date'],
        y=df['Seven_Day_Avg'],
        name="7-Day Moving Avg",
        mode='lines', 
        line = dict(color='firebrick', width=3)
    ))

请注意,折线图是通过 go.Scatter() 绘制的。这是因为 Plotly 折线图的生成是由于连接散点图。这也意味着,数据点按照它们在数据集中出现的顺序与线连接。因此,在将数据传递给Plotly之前,如果原始的排序不能得到所需的输出,你可能需要在此之前对数据进行显式排序。

使用 Plotly 的基本交互式组合图(图片由作者提供)

自定义悬停工具框(Hover-over Tooltips)

默认情况下,Plotly 会自动在工具框中显示 x 和 y 轴的值。例如,在上图中,如果将鼠标悬停在折线图中的任何数据点上,则会出现一个工具框,并显示新增案例的日期以及 7 天内平均变化量。

我们可以通过在数据框中创建一个叫“text”的新列,从而自定义工具框的外观。这个“text”列显示了我们想要在工具框中显示的信息,并定义了工具框的外观和感觉。然后,通过将这些信息分配给 hoverinfo 参数,将此列“文本”传递给 go.Scatter() 迹线。

下列代码可以在数据框中创建“文本”列。HTML 元素,也被称为 Boldface 元素,在此处用于将“State”字段的文本设为粗体。


HTML 元素在文本中产生一个换行符,之后的文本再次从文本块的下一行开始。

hover_text = []
for index, row in df.iterrows():
    hover_text.append(('<b>{State}</b><br><br>'+
                      'Snapshot Date: {Snapshot_Date}<br>'+
                      'New Cases: {New_Cases_formatted}<br>'+ 
                      '7-Day Moving Avg: {Seven_Day_Avg_formatted}<br>'
                       ).format(
                       State=row['State'],
                       Snapshot_Date=row['Snapshot_Date'],
                       New_Cases_formatted=row['New_Cases_formatted'],
                       Seven_Day_Avg_formatted=row['Seven_Day_Avg_formatted']
                      ))
df['text'] = hover_text

现在,我们将“text”列传递给go.Scatter()中的hoverinfo参数,并检查它在工具框中的外观:

fig = go.Figure()
fig.add_trace(
    go.Bar(
        x=df['Snapshot_Date'],
        y=df['New_Cases'],
        name="New Cases",
        hoverinfo='none', #Do not show tooltip when hovering over the bar chart as this information is repetitive when hovering over the line chart
        marker_line_color='#11457E',
        marker_line_width=2, 
        opacity=0.7)
    )

fig.add_trace(
    go.Scatter(
        x=df['Snapshot_Date'],
        y=df['Seven_Day_Avg'],
        name="7-Day Moving Avg",
        mode='lines', 
        text=df['text'],
        hoverinfo='text', #Pass the 'text' column to the hoverinfo parameter to customize the tooltip
        line = dict(color='firebrick', width=3)
    ))
带有自定义工具框的组合图(图片由作者提供)

看起来不错!让我们再对表格做一些额外的调整,看起来更专业。我们将工具框的背景颜色从红色更改为浅蓝色。我们还可以添加图表标题,并将 x 轴刻度更改为每月(而不是每季度)。所有这些操作都可以通过 fig.update_layout() 实现,代码如下所示。

fig.update_layout(hoverlabel_bgcolor='#DAEEED', #Change the tooltip background color to be light grey
                 title_text='Daily COVID-19 Cases in the U.S.', #Add a chart title
                 title_font_family="Times New Roman",
                 title_font_size = 25,
                 title_font_color="darkblue",
                 title_x=0.25, #Specify the title position
                 xaxis=dict(
                        tickfont_size=10,
                        tickangle = 270,
                        showgrid = True,
                        zeroline = True,
                        showline = True,
                        showticklabels = True,
                        dtick="M1", #Change the x-axis ticks to be monthly
                        tickformat="%b\n%Y"
                        ),)

添加范围滑块(Range Slider)/选择器(Selector)

我们还可以添加范围选择器/滑块,方便用户可以放大到特定的时间序列范围,从而使可视化更具信息性和交互性!这一步操作可以在 fig.update_xaxes() 中通过几行代码轻松实现。

#Add the range slider and selector to the plot
fig.update_xaxes(
    rangeslider_visible=True,
    rangeselector=dict(
        buttons=list([
            dict(count=1, label="1m", step="month", stepmode="backward"),
            dict(count=6, label="6m", step="month", stepmode="backward"),
            dict(count=1, label="YTD", step="year", stepmode="todate"),
            dict(count=1, label="1y", step="year", stepmode="backward"),
            dict(step="all")
        ])
    )
)

fig.show()
交互式组合图(图片由作者提供)

现在,我们基本上已经完成了所有操作!你已经通过 Plotly Go 创建了一个交互式组合图表,通过自定义工具框和范围滑块/选择器可视化美国每日 Covid-19 病例趋势。正如你所看到的那样,Plotly 图形库功能强大、界面优雅且高度可定制。通过Plotly图形库,你可以轻松高效执行创建复杂的交互式可视化任务。我希望这篇文章对您有所帮助,并做好准备,将 Plotly 添加到你的数据科学家的工具包中。

参考资料及资料来源:

1. Plotly 的官方文档页面:https://plotly.com/python/

2. 数据来源:来自疾病控制与预防中心 (CDC) 网站 (https://covid.cdc.gov/covid-data-tracker/#trends_dailycases) 的开放 Covid-19 跟踪器数据集

原文作者:Sharone Li
翻译作者:Lia
美工编辑:过儿
校对审稿:Jiawei Tong
原文链接:https://towardsdatascience.com/leap-from-matplotlib-to-plotly-a-hands-on-tutorial-for-beginners-d208cd9e6522