HOWTO · Plotly

Plotly 线形图

本文教你在 Python 中使用 Plotly 的 line() 函数创建折线图。

本页内容

折线图用一条连续线连接各个数据点,便于展示某个值沿时间等有序坐标轴的变化。在 Python 中,最快的创建方式是使用 Plotly Express 的折线图函数 px.line:传入 x 轴和 y 轴数据后,它会返回一个 Figure 对象,fig.show() 可在浏览器或 Notebook 中将其渲染出来。

使用 Plotly Express 创建折线图

Plotly Express 是 Plotly 的高级绘图接口。px.line 接收你的数据并构建一个 Figure,同时为你提供的每个序列存储一个轨迹(trace),也就是一条线。

运行下面的示例:

本节中的代码以及显示的标签或输出仍为英文。

import pandas as pd
import plotly.express as px

df = pd.DataFrame(
    {
        "day": ["Mon", "Tue", "Wed", "Thu"],
        "team_a": [3, 4, 3, 5],
        "team_b": [2, 3, 2, 4],
    }
)
fig = px.line(df, x="day", y=["team_a", "team_b"], width=500, height=400)
print(len(fig.data))
2

width 和 height 参数以像素为单位设置图表大小;向 y 传入包含两列的列表会绘制两条线,因此打印出的轨迹数量为 2。列名会成为图例条目。

在最后一行加入 fig.show(),即可在浏览器中打开渲染后的图表(在 Jupyter Notebook 中,直接对 fig 求值会自动显示图表)。结果如下:

包含两个折线序列、四个 x 轴标签和图例的 Plotly 折线图

为 x 轴和 y 轴选择数据

px.line 接受两种形式的数据。你可以直接向 x 和 y 传入普通 Python 序列,也可以把 DataFrame 作为第一个参数,并把要绘制的列名传给 x 和 y。x 将数据点定位在水平轴上,y 将其定位在垂直轴上;Plotly 会按值出现的顺序连接这些点。

本节中的代码以及显示的标签或输出仍为英文。

import pandas as pd
import plotly.express as px

sequence_fig = px.line(x=[1, 2, 3, 4], y=[10, 15, 13, 18])

df = pd.DataFrame(
    {"month": ["Jan", "Feb", "Mar", "Apr"], "revenue": [10, 15, 13, 18]}
)
column_fig = px.line(df, x="month", y="revenue")

print(len(sequence_fig.data), len(column_fig.data))
1 1

这两种形式都会生成只含一条线的图形。要绘制多个序列,可以像第一个示例那样,为宽格式数据的 y 传入列名列表;也可以让数据保持长格式——每行一个观测值,并用一列标明序列名称——再把该列传给 color。如果你希望坐标轴标题或图例名称不同于列名,可以使用 labels 参数;它是一个把列名映射为显示文本的字典。

自定义线条、颜色和标记

对于长格式数据,color 会为每个组绘制一条线并添加图例,line_dash 会按组改变每条线的虚线样式,symbol 会按组改变每个数据点处的标记符号(设置 symbol 后会自动显示标记;否则可用 markers=True 强制显示)。text 参数设置逐点显示的文本标签,可通过 fig.update_traces(mode="lines+markers+text") 展示;title 则给图表添加标题。

Plotly 会从默认序列中选择颜色和虚线样式。可以用 color_discrete_sequence 覆盖它们——它可以是一个命名调色板,如 px.colors.qualitative.Light24 或 Dark24,也可以是你自己的列表——以及 line_dash_sequence,后者会在 solid、dot、dash、longdash、dashdot 和 longdashdot 等有效虚线样式中循环。

本节中的代码以及显示的标签或输出仍为英文。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(
    df,
    x="year",
    y="lifeExp",
    color="country",
    line_dash="country",
    color_discrete_sequence=px.colors.qualitative.Light24,
    line_dash_sequence=["longdashdot", "dash"],
    width=600,
    height=400,
)
print(len(fig.data), fig.data[0].line.dash)
2 longdashdot

px.data.gapminder() 加载 Plotly 自带的数据集,query 调用保留大洋洲的两个国家,因此图表中有两条线。第一个序列采用 line_dash_sequence 中的第一项。

两条折线使用 Light24 调色板重新着色并采用不同虚线样式的 Plotly 折线图

要精确控制单独的线条,可使用 color_discrete_map;它是从组名到 CSS 颜色的字典。未包含在该映射中的组仍会使用当前序列中的颜色。示例代码中的组名保持英文,因为它们必须与数据集中的值一致。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(
    df,
    x="year",
    y="lifeExp",
    color="country",
    color_discrete_map={"Australia": "black", "New Zealand": "yellow"},
    width=600,
    height=400,
)
print(fig.data[0].name, fig.data[0].line.color)
Australia black

澳大利亚折线绘制为黑色、新西兰折线绘制为黄色的 Plotly 折线图

将图表拆分为分面并更改坐标轴刻度

facet_col 和 facet_row 会把图表拆分为子图网格,所选列的每个值对应一个子图,从而可以并排比较各个序列。facet_col_spacing 和 facet_row_spacing 接受 0 到 1 之间的浮点数,用于以绘图区域的比例设置子图之间的间距。

本节中的代码以及显示的标签或输出仍为英文。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(
    df,
    x="year",
    y="lifeExp",
    color="country",
    line_dash="country",
    symbol="country",
    facet_col="country",
    title="Line Chart",
    width=600,
    height=400,
)
print(len(fig.data))
2

两个并排的 Plotly 子图,各自在共享标题下显示一个国家的带标记折线序列

代码中用于数据匹配和显示的英文标签保持原样,因此图中的相应文本仍显示为英文。当数值跨越多个数量级时,可以用 log_x=True 或 log_y=True 将坐标轴切换为对数刻度;随后 Plotly 会用 10 的幂标注刻度。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", log_y=True)
print(fig.layout.yaxis.type)
log

更新轨迹并添加误差线

要绘制误差线,请给 error_y(或用于水平不确定性的 error_x)传入一个列或序列,其中保存每个数据点的不确定范围:

本节中的代码以及显示的标签或输出仍为英文。

import pandas as pd
import plotly.express as px

df = pd.DataFrame(
    {
        "month": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
        "revenue": [102, 118, 110, 131, 125, 140],
        "uncertainty": [6, 8, 5, 9, 7, 10],
    }
)
fig = px.line(df, x="month", y="revenue", error_y="uncertainty", markers=True)
print(len(fig.data[0].error_y.array))
6

图形创建完成后,fig.update_traces 会一次性把轨迹属性应用到每一条线。例如,showlegend=False 会将所有线从图例中移除;opacity 取 0 到 1 之间的值,可以让线条变为半透明——当多个序列重叠时很有用。

import plotly.express as px

df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.line(df, x="year", y="lifeExp", color="country", width=600, height=400)
fig.update_traces(showlegend=False, opacity=0.7)
print(fig.data[0].showlegend, fig.data[0].opacity)
False 0.7

包含两条半透明折线且没有图例的 Plotly 折线图

px.line 构建的是 Scatter 轨迹,因此 Plotly Scatter 参考文档 中的每个选项也都可以用于 fig.update_traces。