如何用Plotly.Express绘制多分组置信区间线图 复刻Seaborn.lineplot效果
Plotly实现带置信区间的分组线图
问题背景
需要在plotly.express中实现类似seaborn.lineplot自带置信区间的分组线图效果,最终输出和Seaborn示例效果一致。
Seaborn参考代码
import plotly.express as px import seaborn as sns import pandas as pd import numpy as np np.random.seed(1) df = pd.DataFrame({'x': np.tile(np.arange(5), 6), 'y': np.random.randn(30), 'hue': np.repeat(['foo', 'bar'], [15, 15])}) sns.lineplot(data=df, x='x', y='y', hue='hue')
原有单组Plotly实现
group = ['hue', 'x'] err = df.groupby(group)['y'].std() / np.sqrt(df.groupby(group)['y'].size()) pdf = df.groupby(group)['y'].mean().reset_index() pdf['2'] = pdf['y'] + 1.96*pdf.set_index(group).index.map(err) pdf['1'] = pdf['y'] - 1.96*pdf.set_index(group).index.map(err) pdf['0'] = pdf['y'] pdf = pdf.drop('y', axis=1) pdf = pd.melt(pdf, id_vars=['x', 'hue']) pdf = pdf.sort_values(['x', 'variable', 'hue'], ascending = True) fig = px.line( pdf[pdf['hue']=='foo'], line_group='hue', x = 'x', y = 'value', color='variable', color_discrete_map = {'0': 'blue', '1': 'blue', '2': 'blue'} ) fig.update_traces(name = 'interval', selector = dict(name = '2'), showlegend=False) fig.update_traces(fill = 'tonexty') fig.update_traces(fillcolor = 'rgba(0,0,0,0)', selector = dict(name = '0')) fig.update_traces(fillcolor = 'rgba(0,0,0,0)', line_color = 'rgba(0, 0, 255, 0.5)', showlegend = False, selector = dict(name = '1')) fig.show()
多组完整实现方案
不需要拆分单组绘图再叠加,直接利用plotly.express的多维度颜色映射,按分组给上下界和均值线分配对应色系,同时调整填充规则即可:
# 置信区间计算逻辑和原有代码一致 group = ['hue', 'x'] err = df.groupby(group)['y'].std() / np.sqrt(df.groupby(group)['y'].size()) pdf = df.groupby(group)['y'].mean().reset_index() pdf['upper'] = pdf['y'] + 1.96*pdf.set_index(group).index.map(err) pdf['lower'] = pdf['y'] - 1.96*pdf.set_index(group).index.map(err) pdf['mean'] = pdf['y'] pdf = pdf.drop('y', axis=1) pdf = pd.melt(pdf, id_vars=['x', 'hue'], var_name='type', value_name='value') pdf = pdf.sort_values(['x', 'hue', 'type'], ascending = True) # 定义分组和线类型对应的颜色映射 color_map = { 'foo_mean': '#1f77b4', 'foo_lower': 'rgba(31, 119, 180, 0.3)', 'foo_upper': 'rgba(31, 119, 180, 0.3)', 'bar_mean': '#ff7f0e', 'bar_lower': 'rgba(255, 127, 14, 0.3)', 'bar_upper': 'rgba(255, 127, 14, 0.3)', } # 拼接分组和线类型作为颜色区分维度 pdf['color_key'] = pdf['hue'] + '_' + pdf['type'] # 一次性绘制所有分组的线 fig = px.line( pdf, x='x', y='value', color='color_key', color_discrete_map=color_map, hover_data={'color_key': False} ) # 批量调整轨迹属性 for hue in ['foo', 'bar']: # 上界轨迹:设置填充、隐藏图例 fig.update_traces( selector={'name': f'{hue}_upper'}, showlegend=False, fill='tonexty', fillcolor=color_map[f'{hue}_upper'] ) # 下界轨迹:隐藏线条、隐藏图例 fig.update_traces( selector={'name': f'{hue}_lower'}, showlegend=False, line_width=0 ) # 均值线:重命名为分组名,正常显示在图例 fig.update_traces( selector={'name': f'{hue}_mean'}, name=hue ) fig.update_layout(legend_title_text='hue') fig.show()
实现说明
- 保留了原有的95%置信区间计算逻辑,仅调整绘图部分参数
- 按hue分组分别设置置信区间的填充颜色和透明度,和Seaborn默认风格对齐
- 最终输出效果和Seaborn示例一致:两个分组的均值折线+半透明置信区间填充带,图例仅显示分组名称
内容的提问来源于stack exchange,提问作者ignoring_gravity
相关产品推荐
相关产品推荐

