Plotly.py 填充面积图(Filled Area Plots)完全指南:从 px.area 到 go.Scatter 的 fill、stackgroup 与渐变填充
2026/9/21 15:18:36 网站建设 项目流程
  • 数据可视化
  • 数据分析

【免费下载链接】plotly.py

The interactive graphing library for Python :sparkles:

项目地址:https://gitcode.com/gh_mirrors/pl/plotly.py
点击查看免费下载

面积图(Filled Area Plot)是数据可视化中表达“量随某个轴累积或变化”的最直观方式之一:它通过把折线与坐标轴(或另一条折线)之间的区域填充为颜色,让读者一眼就能看出趋势、占比与分层结构。本篇技术指南以 Plotly.py 官方文档 doc/python/filled-area-plots.md 为核心骨架,结合仓库内plotly.expressplotly.graph_objects的真实源码实现,系统讲解三类核心能力:用高层接口px.area快速生成堆叠面积图、用底层go.Scatterfill/stackgroup/groupnorm精确控制填充行为,以及较新版本提供的fillgradient渐变填充与 pattern 纹理填充。读完本文,你将能根据数据形态与展示目标,直接选用正确的 API 组合,写出可复制、可运行的面积图代码。

一、先理解面积图的底层机制:go.Scatter.fill

无论是高层接口还是底层接口,Plotly 中所有面积图最终都由scatter类 trace 的fill属性驱动。在 plotly/graph_objs/_scatter.py 的自动生成源码中,fill被定义为一个枚举属性,其取值与语义如下:

取值填充语义
'none'不填充,默认值;若 trace 处于堆叠组中则自动变为'tonexty'/'tonextx'
'tozeroy'向下填充到 y=0(沿 x 轴方向)
'tozerox'向左填充到 x=0(沿 y 轴方向)
'tonexty'填充到前一条 trace 的端点并连线,形成堆叠面积图;若无前序 trace 则退化为'tozeroy'
'tonextx'填充到前一条 trace 的端点(水平方向),无前序 trace 时退化为'tozerox'
'toself'把 trace 自身端点(或分段)闭合为封闭形状
'tonext'填充两条相互完全包围的 trace 之间的空间(如等高线场景),无前序 trace 时表现为'toself'

源码文档字符串还明确了一条关键行为:同属一个stackgroup的 trace 只会填充到组内其他 trace;当存在多个堆叠组、或部分 trace 堆叠部分不堆叠时,若填充关联的 trace 不是连续的,后者会被压到绘制顺序的后面("the later ones will be pushed down in the drawing order")。理解这一点,是后续所有堆叠场景正确性的前提。

二、用plotly.express快速绘制堆叠面积图

2.1 基础用法:px.area

Plotly Express 是 Plotly 的高层接口,px.area即其面积图入口。官方文档给出的第一个示例使用内置的gapminder数据集,按大洲着色、按国家分组绘制人口随年份的堆叠面积图:

import plotly.express as px df = px.data.gapminder() fig = px.area(df, x="year", y="pop", color="continent", line_group="country") fig.show()

这里的语义是:每一块被填充的面积区域对应line_group指定列的一个取值color决定每条折线的颜色,而所有 trace 会通过stackgroup自动堆叠起来。

px.data.gapminder()返回的数据集定义于 plotly/data/init.py(gapminder函数),其每一行代表"某个国家在某一年"的记录,包含countrycontinentyearpop等列;该函数还支持year过滤、datetimes时间类型转换、centroids经纬度附加与return_type返回类型切换等参数,便于按需裁剪数据。

2.2 源码视角:px.area到底做了什么

px.area的实现位于 plotly/express/_chart_types.py。其函数签名完整覆盖了高层绘图所需的全部参数:data_framexyline_groupcolorpattern_shapesymbolhover_namehover_datacustom_datatextfacet_row/facet_colanimation_frame/groupcategory_orderslabelscolor_discrete_sequence/mappattern_shape_sequence/mapsymbol_sequence/mapmarkersorientationgroupnormlog_x/log_yrange_x/range_yline_shapetitlesubtitletemplatewidthheight

关键在最后两行——它把参数直接委托给统一的make_figure流水线,并注入一段trace_patch

return make_figure( args=locals(), constructor=go.Scatter, trace_patch=dict(stackgroup=1, mode="lines", groupnorm=groupnorm), )

这说明三个事实:

  1. px.area生成的底层 trace 类型就是go.Scatter
  2. 它默认设置stackgroup=1(一个名为"1"的堆叠组),所有面积块自动堆叠;
  3. mode="lines"意味着默认只画折线、不画标记点(可通过markers=True开启);
  4. 顶层参数groupnorm会被直接透传到每个 trace,用于归一化堆叠(详见下文)。

也就是说,px.area(df, x=..., y=..., color=...)在底层等价于若干条设置了stackgroupmode='lines'go.Scattertrace,官方文档 plotly/express/_chart_types.py 中对area的 docstring 也明确写道:"In a stacked area plot, each row ofdata_frameis represented as a vertex of a polyline mark in 2D space. The area between successive polylines is filled."

2.3 Pattern 纹理填充(v5.7+ 新增)

面积图除了用颜色区分,还支持"图案/纹理"(hatching / texture)来增强可辨识度,这在打印输出或色盲友好场景下尤其有用。官方文档示例使用medals_long数据集:

import plotly.express as px df = px.data.medals_long() fig = px.area(df, x="medal", y="count", color="nation", pattern_shape="nation", pattern_shape_sequence=[".", "x", "+"]) fig.show()

这里pattern_shape指定用nation列区分图案,pattern_shape_sequence自定义图案序列("."点、"x"交叉、"+"加号)。在 plotly/express/_core.py 中可以看到,当未显式给出pattern_shape_sequence时,Plotly Express 会优先尝试从当前template的 bar trace 继承,否则使用默认序列["", "/", "\\", "x", "+", "."]pattern_shape参数在推断配置时会被映射到底层marker.pattern.shape属性(见同文件第 44 行注释)。

medals_long数据集同样定义于 plotly/data/init.py,为长表(tidy)格式,每行是一个"国家 × 奖牌类型"的组合计数,天然适合px.areacolor/pattern_shape分组。

三、用plotly.graph_objects精确控制填充

当需要精细控制每条 trace 的填充方向、颜色、堆叠与归一化时,直接使用go.Scatter是更灵活的选择。以下小节逐一对应官方文档中的经典场景。

3.1 基础叠加面积图:tozeroy+tonexty

import plotly.graph_objects as go fig = go.Figure() fig.add_trace(go.Scatter(x=[1, 2, 3, 4], y=[0, 2, 3, 5], fill='tozeroy')) # fill down to xaxis fig.add_trace(go.Scatter(x=[1, 2, 3, 4], y=[3, 5, 1, 7], fill='tonexty')) # fill to trace0 y fig.show()
  • 第一条 tracefill='tozeroy':从折线向下填充到 y=0(即 x 轴),形成"山峰"状区块;
  • 第二条 tracefill='tonexty':填充到第一条 trace 的 y 值端点,两者之间形成叠加带。

两条 trace 默认modemarkers+lines,因此会同时显示数据点与折线轮廓。源码文档字符串(见上文fill属性)对'tonexty'的解释是:连接到"前一条 trace"的端点,若无前序 trace 则退化为'tozeroy'——所以本例中第二条 trace 的实际填充区间是"trace1 折线下方、trace0 折线上方"。

3.2 去掉边界线的叠加面积图:mode='none'

如果不希望显示折线与数据点、只要纯色块,可将mode设为'none',它会覆盖默认的markers+lines

import plotly.graph_objects as go fig = go.Figure() fig.add_trace(go.Scatter(x=[1, 2, 3, 4], y=[0, 2, 3, 5], fill='tozeroy', mode='none' # override default markers+lines )) fig.add_trace(go.Scatter(x=[1, 2, 3, 4], y=[3, 5, 1, 7], fill='tonexty', mode= 'none')) fig.show()

这种"无轮廓"样式常用于呈现平滑的分层总量,视觉上更干净。结合px.areatrace_patch=dict(mode="lines")(plotly/express/_chart_types.py)可以看到,高层接口默认保留lines而关闭markers,与这里的mode='none'形成对照——两种形态都可以通过mode自由切换。

3.3 内部填充:只填充两条 trace 之间的区域

'tonexty'并不要求第一条 trace 必须填充。下面的例子中,trace0 的fill=None、只画indigo折线,trace1 的fill='tonexty'填充到 trace0 之间,从而只突出两条曲线夹出的带状区域:

import plotly.graph_objects as go fig = go.Figure() fig.add_trace(go.Scatter(x=[1, 2, 3, 4], y=[3, 4, 8, 3], fill=None, mode='lines', line_color='indigo', )) fig.add_trace(go.Scatter( x=[1, 2, 3, 4], y=[1, 6, 2, 6], fill='tonexty', # fill area between trace0 and trace1 mode='lines', line_color='indigo')) fig.show()

填充的默认颜色是"当前线条颜色的半透明变体"(fillcolor属性文档:"Defaults to a half-transparent variant of the line color"),因此这里两条 indigo 折线之间会呈现一层半透明 indigo 色带,既保留数据曲线又突出区间差异。官方文档将此场景称为 "Interior Filling for Area Chart",即"内部填充"。

3.4 渐变填充fillgradient(5.20+ 新增)

fill的 scatter trace 支持fillgradient——一个定义渐变参数的dict。官方文档给出的水平渐变示例:

import plotly.graph_objects as go fig = go.Figure( [ go.Scatter( x=[1, 2, 3, 4], y=[3, 4, 8, 3], fill=None, mode="lines", line_color="darkblue", ), go.Scatter( x=[1, 2, 3, 4], y=[1, 6, 2, 6], fill="tonexty", mode="lines", line_color="darkblue", fillgradient=dict( type="horizontal", colorscale=[(0.0, "darkblue"), (0.5, "royalblue"), (1.0, "cyan")], ), ), ] ) fig.show()

fillgradient的完整属性集合定义于自动生成的 plotly/graph_objs/scatter/_fillgradient.py,其_valid_props = {"colorscale", "start", "stop", "type"},各属性语义如下:

  • type:渐变的类型/方向,枚举值为['radial', 'horizontal', 'vertical', 'none'],默认'none'(即退化为纯色fillcolor)。文档描述它同时决定colorscale的施加方向。
  • colorscale:渐变使用的颜色刻度,支持三种写法(见 plotly/graph_objs/scatter/_fillgradient.py):
    1. 一组颜色列表,会被均匀插值成 colorscale(如["darkblue", "cyan"]);
    2. 归一化位置(0~1)与颜色的二元组列表,例如[(0.0, 'green'), (0.5, 'red'), (1.0, 'rgb(0, 0, 255)')]
    3. 命名 colorscale 名称(plotly.colorssequentialdivergingcyclical模块预置的几十种,如'viridis''magma''blues'等),追加'_r'后缀可反转方向。
  • start/stop:渐变沿方向轴的起始/结束绝对坐标。例如type='horizontal'时从 x 坐标start处开始渐变;省略时分别取 trace 沿该轴的最低值与最高值。径向渐变('radial')会忽略这两个参数——渐变从中心到距中心最远点展开。

需要说明的是,fillgradient仅在填充有效(即fill'none')时才有意义;当fillgradient被指定时,fillcolor会被忽略(见 plotly/graph_objs/_scatter.py 中fillcolorfillgradient属性的文档说明)。渐变填充功能自 5.20 版本起可用,请确保使用不低于该版本的 Plotly。

3.5 堆叠面积图:stackgroup

stackgroup参数把同一组内各 trace 的 y 值(水平方向则为 x 值)相加:组内 trace 依次"填到"组内下一条 trace 之上,形成堆叠。官方文档示例:

import plotly.graph_objects as go x=['Winter', 'Spring', 'Summer', 'Fall'] fig = go.Figure() fig.add_trace(go.Scatter( x=x, y=[40, 60, 40, 10], hoverinfo='x+y', mode='lines', line=dict(width=0.5, color='rgb(131, 90, 241)'), stackgroup='one' # define stack group )) fig.add_trace(go.Scatter( x=x, y=[20, 10, 10, 60], hoverinfo='x+y', mode='lines', line=dict(width=0.5, color='rgb(111, 231, 219)'), stackgroup='one' )) fig.add_trace(go.Scatter( x=x, y=[40, 30, 50, 30], hoverinfo='x+y', mode='lines', line=dict(width=0.5, color='rgb(184, 247, 212)'), stackgroup='one' )) fig.update_layout(yaxis_range=(0, 100)) fig.show()

源码文档(plotly/graph_objs/_scatter.py)对这一机制有权威描述:stackgroup是一个字符串,同一stackgroup的 trace 的 y 值(或orientation='h'时的 x 值)会被相加;开启堆叠会自动打开填充,默认使用'tonexty'(水平方向为'tonextx');同一组内的 trace 只会填充到组内其他 trace;多个堆叠组并存或部分堆叠时,填充关联 trace 若不连续会被调整绘制顺序。示例代码还展示了两个实用细节:用line=dict(width=0.5, color=...)控制组内折线宽度与颜色,用fig.update_layout(yaxis_range=(0, 100))把 y 轴范围固定,避免堆叠总量超出可视区域。

3.6 归一化堆叠:groupnorm='percent'

groupnorm只对使用stackgroup的 trace 生效,且只取组内第一个出现的groupnorm(含visibleFalse的 trace)。官方文档示例将各组值归一化为百分比,得到"占比面积图":

import plotly.graph_objects as go x=['Winter', 'Spring', 'Summer', 'Fall'] fig = go.Figure() fig.add_trace(go.Scatter( x=x, y=[40, 20, 30, 40], mode='lines', line=dict(width=0.5, color='rgb(184, 247, 212)'), stackgroup='one', groupnorm='percent' # sets the normalization for the sum of the stackgroup )) fig.add_trace(go.Scatter( x=x, y=[50, 70, 40, 60], mode='lines', line=dict(width=0.5, color='rgb(111, 231, 219)'), stackgroup='one' )) fig.add_trace(go.Scatter( x=x, y=[70, 80, 60, 70], mode='lines', line=dict(width=0.5, color='rgb(127, 166, 238)'), stackgroup='one' )) fig.add_trace(go.Scatter( x=x, y=[100, 100, 100, 100], mode='lines', line=dict(width=0.5, color='rgb(131, 90, 241)'), stackgroup='one' )) fig.update_layout( showlegend=True, xaxis_type='category', yaxis=dict( type='linear', range=[1, 100], ticksuffix='%')) fig.show()

关键点:

  • 只有第一条 trace 需要显式写groupnorm='percent'(组内其他 trace 可省略),因为源码规定只取组内第一个groupnorm
  • 每个 x 位置处,各 trace 的 y 值除以该位置组内总和,得到百分比。groupnorm还有'fraction'取值(归一化为 0~1 的小数),'percent'则对应 0~100;
  • 布局层通过xaxis_type='category'把 x 当成分类轴('Winter'等文本标签),yaxis设置range=[1, 100]ticksuffix='%'让纵轴以百分比形式展示。

3.7 选择 Hover 作用区域:hoveron='points+fills'

默认情况下 hover 只作用于数据点。通过hoveron可以扩展(或限制)hover 的命中区域,官方文档示例对比了'points+fills''points'两种模式:

import plotly.graph_objects as go fig = go.Figure() fig.add_trace(go.Scatter(x=[0,0.5,1,1.5,2], y=[0,1,2,1,0], fill='toself', fillcolor='darkviolet', hoveron = 'points+fills', # select where hover is active line_color='darkviolet', text="Points + Fills", hoverinfo = 'text+x+y')) fig.add_trace(go.Scatter(x=[3,3.5,4,4.5,5], y=[0,1,2,1,0], fill='toself', fillcolor = 'violet', hoveron='points', line_color='violet', text="Points only", hoverinfo='text+x+y')) fig.update_layout( title = "hover on <i>points</i> or <i>fill</i>", xaxis_range = [0,5.2], yaxis_range = [0,3] ) fig.show()

本例还展示了两个相关能力:

  • fill='toself':把折线端点闭合为封闭多边形(两个山峰状区域),配合fillcolor指定填充色;
  • hoveron的可选枚举([plotly/graph_objs/_scatter.py](https://link.gitcode.com/i/a1934fb2ab2da35c794ce6176bbbc0d5)附近源码)包括'points''fills''points+fills'等:当 fill 为'toself''tonext'且折线未完全封闭时,'points'会退化为'fills'行为——即悬停在点内与填充区域内均触发 hover;
  • hoverinfo='text+x+y'让 tooltip 同时显示自定义text、x 与 y 值。

四、参数速查与选择指南

综合官方文档与源码,将两条 API 路径的关键参数整理如下,便于快速决策:

4.1px.area(高层接口,自动堆叠)

参数作用说明
data_frame数据源长表/宽表均可,参考 plotly.express 参数文档
x/y坐标列必填
line_group分块列每个取值生成一块被填充的面积
color颜色分组决定各面积块颜色
pattern_shape纹理分组v5.7+,配合pattern_shape_sequence自定义纹理
groupnorm归一化透传到底层 trace,取值'fraction'/'percent'
markers是否画数据点默认False(底层mode='lines'
orientation堆叠方向'v'(默认)或'h'
line_shape连线形状'linear''spline''hv'
title/subtitle标题直接写入layout.title

4.2go.Scatter(底层接口,精确控制)

属性作用关键取值/说明
fill填充方式'none'/'tozeroy'/'tozerox'/'tonexty'/'tonextx'/'toself'/'tonext'
fillcolor填充颜色默认取线条颜色的半透明变体
fillgradient渐变填充5.20+;dict(type=..., colorscale=..., start=..., stop=...)
stackgroup堆叠组同名分组内 y 值相加,自动开启fill='tonexty'
groupnorm组内归一化'fraction'/'percent',只取组内首个值
hoveronhover 区域'points'/'fills'/'points+fills'
mode渲染模式'lines'/'markers'/'lines+markers'/'none'

如何选择:需要快速出图、数据是整洁的 DataFrame 时优先px.area(它自动完成stackgroup=1mode='lines'的配置,见 plotly/express/_chart_types.py);需要对每条 trace 单独控制填充方向、颜色、hover 与渐变时,使用go.Scatter;两者可以在同一go.Figure中混用。

五、测试佐证:px.area在仓库中的验证覆盖

仓库测试对px.area有系统覆盖,可作为 API 行为正确性的佐证:

  • tests/test_optional/test_px/test_pandas_backend.py:验证 pandas 的df.plot.area()/df.plot(kind="area")px.area的等价映射,说明px.area也参与 pandas 后端兼容;
  • tests/test_optional/test_px/test_px_input.py:在输入校验测试中,px.areapx.scatterpx.line等一同被参数化覆盖;
  • tests/test_optional/test_px/test_px_wide.py:验证px.area对宽表(wide-form)数据的正确处理。

这些测试文件位于tests/test_optional/test_px/目录,是深入理解px.area边界行为(如宽表输入、pandas 后端)的第一手资料。

六、实践建议与常见坑

  1. 堆叠与填充的自动联动:只要设置了stackgroupfill就会被自动设为'tonexty'(水平为'tonextx')。若想堆叠但不填充,需要显式覆盖fill='none'
  2. groupnorm只认第一个:归一化值只取组内第一条 trace 的设置,因此务必把groupnorm写在该组第一条 trace 上,否则可能得到意外结果。
  3. 渐变填充的版本前提fillgradient需要 Plotly 5.20+;低版本下该属性不可用,建议升级并留意fillcolorfillgradient的互斥关系。
  4. tonextytozeroy的退化规则:没有前序 trace 时,'tonexty'/'tonextx'会退化为'tozeroy'/'tozerox',因此"第一条 trace"通常是'tozeroy'fill=None
  5. 坐标系与填充方向'tozeroy'填充到 y=0、'tozerox'填充到 x=0;绘制水平堆叠面积图(orientation='h')时使用 x 方向的填充与堆叠。
  6. 颜色辨识:多分类堆叠时,除了color还可叠加pattern_shape(纹理)以兼顾打印与色盲场景,纹理序列支持".""x""+""/""\\"""(空)等。

参考与延伸阅读

  • 本文核心依据:doc/python/filled-area-plots.md
  • 高层接口实现:plotly/express/_chart_types.py
  • 底层属性定义:plotly/graph_objs/_scatter.py(fill)、plotly/graph_objs/scatter/_fillgradient.py(fillgradient
  • 内置数据集:plotly/data/init.py(gapminder)、plotly/data/init.py(medals_long
  • 纹理与序列默认值逻辑:plotly/express/_core.py
  • 相关测试:tests/test_optional/test_px/test_pandas_backend.py、tests/test_optional/test_px/test_px_wide.py
  • 相邻主题:纹理/图案填充详解见 doc/python/pattern-hatching-texture.md,Plotly Express 的通用参数与数据结构见 doc/python/px-arguments.md,样式定制见 doc/python/styling-plotly-express.md
  • 数据可视化
  • 数据分析

【免费下载链接】plotly.py

The interactive graphing library for Python :sparkles:

项目地址:https://gitcode.com/gh_mirrors/pl/plotly.py
点击查看免费下载
上一篇:告别混乱实验!用DVC+Git管理EfficientNet-PyTorch模型训练全流程
下一篇:终极指南:如何快速从PDF中提取表格数据?Tabula表格提取神器详解

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询