You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加标注时数据消失问题求助(Plotly分面柱状图)

Plotly分面柱状图添加子图标注问题

问题场景

  • 使用Plotly绘制同时设置facet_row和facet_col的分面柱状图,需要为每个子图添加对应facet_row的标注
  • 尝试xref=paper时,标注位置偏差明显;且facet_col数量随数据集动态变化,进一步加剧位置偏移问题
  • 希望通过遍历facet_col和facet_row值,基于子图轴域(xref=xn)添加标注(标注位于子图上方),但该方法报错
  • 尝试某方法后标注位置稳定,但图表所有数据消失,相关代码如下:
import pandas as pd
import numpy as np
import plotly.express as px

# Define the date range and number of days
start_date = '2023-01-01'
end_date = '2023-01-31'
dates = pd.date_range(start=start_date, end=end_date)

# Define the metric names and markets
metric_names = ['Metric1', 'Metric2', 'Metric3', 'Metric4', 'Metric5']
markets = ['Market1', 'Market2', 'Market3', 'Market4', 'Market5']

# Create a product of dates, metric names, and markets
date_metric_market_triples = [(date, metric, market) for date in dates for metric in metric_names for market in markets]

# Create the DataFrame
df = pd.DataFrame(date_metric_market_triples, columns=['Date', 'Metric_Name', 'Market'])

# Add random metric values
df['Metric_Value'] = np.random.randint(0, 100, size=len(df))

# Group and reset the index to make plotting easier
grouped_data = df.groupby(['Date', 'Metric_Name', 'Market']).sum().reset_index()

# Creating the bar plot with Plotly Express
fig = px.bar(grouped_data, x='Date', y='Metric_Value',
             facet_col='Market', facet_row='Metric_Name',
             category_orders={"Metric_Name": ['Metric1', 'Metric2', 'Metric3', 'Metric4', 'Metric5'],
                              "Market": ['Market1', 'Market2', 'Market3', 'Market4', 'Market5']},
             title='Sum of Metric Values by Date, Metric, and Market')

# Adjust layout for better visibility
fig.update_layout(
    height=1200,  # Increase figure height for better visibility
    width=1600    # Increase figure width to accommodate more facets
)

# Adding annotations for MetricName in each facet without overwriting plot data
for i, metric_name in enumerate(metric_names):
    for j, market in enumerate(markets):
        fig.add_annotation(
            dict(
                x=0.5,  # Position of the annotation at the middle of the x-axis
                y=1.05,  # Position slightly above the top of the y-axis within each subplot
                text=metric_name,  # Text to display (Metric Name)
                xref=f"x{len(markets) * i + j + 1}",  # Correct axis reference for x-axis
                yref=f"y{len(markets) * i + j + 1}",  # Correct axis reference for y-axis
                showarrow=False,
                font=dict(size=10, color="black"),
                xanchor='center',  # Center align text
                yanchor='bottom'   # Bottom align text relative to the specified y coordinate
            )
        )

# Show the figure
fig.show()

解决方案

问题核心是标注的坐标参考系错误:原代码中xref="xN"指向的是子图的数据轴,使用x=0.5会被解析为数据值0.5而非子图的相对位置,导致标注偏离预期甚至干扰图表渲染。

只需将xref和yref修改为子图轴的domain域(坐标范围0-1,对应子图的整体宽高),即可稳定在每个子图上方添加标注:

# 替换原标注循环代码
for i, metric_name in enumerate(metric_names):
    for j, market in enumerate(markets):
        # 计算子图轴索引:行优先,从1开始
        subplot_idx = i * len(markets) + j + 1
        fig.add_annotation(
            x=0.5,  # 子图水平居中位置
            y=1.05,  # 子图顶部上方5%位置
            text=metric_name,
            # 使用子图的domain作为坐标参考
            xref=f"x{subplot_idx} domain",
            yref=f"y{subplot_idx} domain",
            showarrow=False,
            font=dict(size=10, color="black"),
            xanchor='center',
            yanchor='bottom'
        )

修改后,标注会准确显示在对应子图的顶部居中位置,同时不会影响原有图表数据的渲染,且适配facet_col数量动态变化的场景。

内容的提问来源于stack exchange,提问作者Matt G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 02:07:47