Plotly双Y轴柱状图(固定汇率转换)更优实现方案咨询
问题描述
我需要用Plotly Graph Objects绘制带双Y轴的堆叠柱状图,两个Y轴对应固定转换系数的不同货币(USD和Euro,转换系数为1.5)。目前的实现是为每个类别绘制两个轨迹,将第二个轨迹设为透明、隐藏图例并关闭悬浮信息,虽然能生效但维护繁琐。当前代码如下:
import pandas as pd import numpy as np import plotly.graph_objects as go from plotly.subplots import make_subplots # make up some data dates = pd.DataFrame(pd.date_range('1/1/2023','1/7/2023'), columns=['date']) dates["key"] = 0 items = pd.DataFrame(["A","B","C"], columns=['items']) items["key"] = 0 df = dates.merge(items,on="key",how="outer").drop("key",axis=1) df['price_USD'] = np.random.randint(0, 100, df.shape[0]) df['price_EURO'] = df['price_USD']/1.5 fig = make_subplots(specs=[[{"secondary_y": True}]]) for item, _df in df.groupby("items",sort=True): ## we may set the colors of the individual items manually here fig.add_trace( go.Bar( x=_df["date"], y=_df["price_USD"], showlegend=True, name=item, opacity=1.0, #color=color, legendgroup=item ), secondary_y=False, ) # invisible trace fig.add_trace( go.Bar( x=_df["date"], y=_df["price_EURO"], showlegend=False, opacity=0.0, name="", hoverinfo="skip", legendgroup=item ), secondary_y=True, ) fig.update_layout(barmode="stack") fig.update_yaxes(title_text="<b>Cost USD", secondary_y=False) fig.update_yaxes(title_text="<b>Cost Euro", showgrid=False, secondary_y=True) fig.show()

请问有没有更简洁的实现方式?
简洁实现方案
不需要添加隐形轨迹,直接通过配置第二个Y轴的刻度值和刻度文本,基于第一个Y轴的数值进行固定系数转换即可。这样仅需绘制一组USD的柱状轨迹,第二个Y轴仅负责显示转换后的Euro刻度,大幅简化代码维护成本。
实现代码
import pandas as pd import numpy as np import plotly.graph_objects as go from plotly.subplots import make_subplots # 生成模拟数据 dates = pd.DataFrame(pd.date_range('1/1/2023','1/7/2023'), columns=['date']) dates["key"] = 0 items = pd.DataFrame(["A","B","C"], columns=['items']) items["key"] = 0 df = dates.merge(items,on="key",how="outer").drop("key",axis=1) df['price_USD'] = np.random.randint(0, 100, df.shape[0]) conversion_rate = 1.5 # USD转Euro的固定转换系数 fig = make_subplots(specs=[[{"secondary_y": True}]]) # 仅绘制USD的堆叠柱状轨迹 for item, _df in df.groupby("items",sort=True): fig.add_trace( go.Bar( x=_df["date"], y=_df["price_USD"], showlegend=True, name=item, legendgroup=item ), secondary_y=False, ) # 配置主Y轴(USD) fig.update_yaxes(title_text="<b>Cost USD</b>", secondary_y=False) # 配置次Y轴(Euro):复用主Y轴刻度值,显示转换后的Euro文本 usd_ticks = fig.layout.yaxis.tickvals if usd_ticks: euro_ticks = [tick / conversion_rate for tick in usd_ticks] fig.update_yaxes( title_text="<b>Cost Euro</b>", tickvals=usd_ticks, ticktext=[f"{tick:.2f}" for tick in euro_ticks], showgrid=False, secondary_y=True ) fig.update_layout(barmode="stack") fig.show()
方案优势
- 仅需维护一组柱状轨迹,避免重复代码
- 转换系数统一管理,修改时仅需调整
conversion_rate变量 - 次Y轴刻度与主Y轴严格对应,保证数据展示的准确性
内容的提问来源于stack exchange,提问作者Raphael Roth
相关产品推荐
相关产品推荐

