英文:
Plotly plot single trace with 2 yaxis
问题
我有一个Plotly图形对象的柱状图,我想要显示两个y轴(不同的货币,所以转换因子是恒定的)。
目前,我每次绘制一个踪迹,而对于第二个踪迹,我将不透明度设置为0,禁用图例和悬停信息。这个方法虽然可行,但维护起来有些繁琐。
我了解https://plotly.com/python/multiple-axes/。
我的当前解决方案如下:
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])
df['price_EURO'] = df['price_USD']/1.5
fig = make_subplots(specs=[[{"secondary_y": True}]])
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,
opacity=1.0,
#color=color,
legendgroup=item
),
secondary_y=False,
)
# 隐形的踪迹
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()
是否有更简洁的方法来做这个?
英文:
I have a plotly graph object bar chart for which I want to display 2 y-axis (different currencies, so the conversion factor ist constant).
Currently I plot 1 trace each, while for the second one I set opacity to 0, disable the legend and hoverinfo. This hack works, but is ugly to maintain.
I'm aware of https://plotly.com/python/multiple-axes/
my current solution looks like this
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()
Is there a cleaner way to do this?
答案1
得分: 5
可以使用另一边作为“scaleanchor”并提供缩放。然后不再需要加倍数据。
英文:
One can use the other side as a scaleanchor
and provide the scaling. Doubling the data is then not necessary anymore.
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
np.random.seed(1)
RATIO = 1.5
# 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])
# This is not needed more, at least for displaying it
#df['price_EURO'] = df['price_USD']/ RATIO
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,
)
# Add a dummy trace to activate the second axis
fig.add_trace(
go.Bar(visible=False),
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)
# Set scale according to the other axis and the defined ratio
# the constraint assures that it is bottom aligned
fig.update_layout(yaxis2=dict(scaleanchor="y1", scaleratio=RATIO, constraintoward="bottom"))
fig.show()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论