Plotly分面网格绘制双均值垂直线的问题求助
解决Plotly分面子图添加两条分组均值垂直线的问题
问题说明
需要在Plotly分面网格的每个子图中绘制两条垂直线,分别展示不同val分组下的price均值。当前代码按cut字段分面展示带val颜色区分的直方图,但仅能显示一条均值线,无法成功绘制两条。
原代码
import seaborn as sns import plotly.express as px import numpy as np # 原代码遗漏numpy导入,需补充 diamonds = sns.load_dataset('diamonds') diamonds['val'] = np.random.randint(1, 3, diamonds.shape[0]) grpval = diamonds.groupby(['cut','val'])['price'].mean() print(grpval) fig = px.histogram(data_frame=diamonds, x='price', facet_col='cut', color = "val", facet_col_wrap = 2, ) for c,idx in zip(diamonds['cut'].unique(),[(1,1),(1,2),(2,1),(2,2),(3,1)]): df = diamonds[diamonds['cut'] == c] fig.add_vline(x=df['price'].tail(1).values[0], line_width=1, line_dash='solid', line_color='red', row=idx[0], col=idx[1]) fig.show()
问题分析
原代码存在两个核心问题:
- 循环仅添加了一条垂直线,且取的是
price列最后一个值,并非val分组的均值 - 未遍历每个
cut下的两个val分组,无法分别添加对应均值的垂直线
修正后的代码
import seaborn as sns import plotly.express as px import numpy as np diamonds = sns.load_dataset('diamonds') diamonds['val'] = np.random.randint(1, 3, diamonds.shape[0]) # 按cut和val分组计算price均值,转为DataFrame方便遍历 grpval = diamonds.groupby(['cut','val'])['price'].mean().reset_index() fig = px.histogram(data_frame=diamonds, x='price', facet_col='cut', color="val", facet_col_wrap=2, ) # 定义val对应的颜色,与直方图颜色保持一致 val_colors = {1: px.colors.qualitative.Plotly[0], 2: px.colors.qualitative.Plotly[1]} # 每个cut对应的子图位置映射 cut_positions = [(1,1),(1,2),(2,1),(2,2),(3,1)] for cut, (row, col) in zip(diamonds['cut'].unique(), cut_positions): # 获取当前cut下的两个val均值数据 cut_means = grpval[grpval['cut'] == cut] for _, mean_row in cut_means.iterrows(): # 为每个val分组添加对应均值的垂直线 fig.add_vline( x=mean_row['price'], line_width=2, line_dash='dash', line_color=val_colors[mean_row['val']], row=row, col=col, annotation_text=f'val={mean_row["val"]}均值', annotation_position='top right' ) fig.show()
修正要点
- 将分组后的
grpval转为结构化DataFrame,便于按cut和val遍历均值 - 为
val分组分配与直方图匹配的颜色,保证视觉一致性 - 嵌套循环实现:先遍历每个
cut及其子图位置,再遍历该cut下的两个val分组,分别添加对应均值的垂直线 - 可选添加标注文本,明确每条线对应的分组均值含义
内容的提问来源于stack exchange,提问作者tonydanza123
相关产品推荐
相关产品推荐

