提问者:小点点

如何设置分组支线?


我正在尝试使用Ploly将分组箱图绘制为网格,其中包含来自数据帧的数据。例如,如果我们有一个数据框,

import plotly.express as px
df = px.data.tips() 

total_bill  tip sex smoker  day time    size
0   16.99   1.01    Female  No  Sun Dinner  2
1   10.34   1.66    Male    No  Sun Dinner  3
2   21.01   3.50    Male    No  Sun Dinner  3
3   23.68   3.31    Male    No  Sun Dinner  2
4   24.59   3.61    Female  No  Sun Dinner  4

我可以画一个图如下(例如:日=星期五):

import plotly.graph_objects as go
import plotly.express as px

df_plot=df[df['day']== 'Fri']
fig = px.box(df_plot, x='time', y="total_bill", color="sex",width=600, height=400)
fig.show()

如果我想绘制多个次要情节,例如,每天一个,我不确定如何在情节中做到这一点。这是我尝试的:

fig = make_subplots(rows=2, cols=2)

for v in range(4):
  for i, met in enumerate(df['day'].unique()): #'Sun', 'Sat', 'Thur', 'Fri'
    df_plot=df[df['day']== met] 
    for t in px.box(df_plot, x="time", y=f"total_bill", color='sex').data:
        fig.add_trace(t, row=(v//2)+1, col=(v%2)+1)

fig.update_layout(
    boxmode="group", margin={"l": 0, "r": 0, "t": 20, "b": 0}
).update_traces(showlegend=True) 

这给出了一个看起来很奇怪的情节。我做错了什么?此外,在带有情节的子情节网格中,我如何为每个情节绘制一个图例而不是图例。


共2个答案

匿名用户

您已经收到了一个似乎产生所需结果的答案。但是由于您似乎急于知道如何使用指定的设置来做到这一点,我想向您展示如何做到这一点。我还确保下面的完整片段也处理了图例。

你最初设置的问题似乎源于图。add_trace(t, row=(v//2)1,col2=(v%2)1)。你的图变得奇怪的原因是在px.box中为t生成的痕迹(df_plot,x="time",y=f"total_bill",颜色='sex').data:没有正确地向子图索引。(v//2)1看起来不错,但是col1=(v%2)1)有点问题。这里你需要的是一个在1和2之间改变的索引。在下面的片段中,你可以看到我已经使用以下方法解决了这个问题:

from itertools import cycle
cols = cycle([1,2])
c = next(cols)

这可能不是最有效的方法,但我一直在其他挑战中使用它,在这种情况下它也很有用。如果你打印出c,你会看到你得到:[1,1,2,2,1,1,1,2,2]。这正是你需要确保第一个子图的两个第一个跟踪最终在子图1中的row=1col1=1,依此类推。

关于你关于传说的第二个问题,这是通过以下方式处理的:

fig.add_trace(t.update(showlegend=True if i == 0 else False), row=r, col=c)
import plotly.express as px
from plotly.subplots import make_subplots
from itertools import cycle

df = px.data.tips()

fig = make_subplots(rows=2, cols=2, subplot_titles = df['day'].unique())

cols = cycle([1,2])

for i, met in enumerate(df['day'].unique()): #'Sun', 'Sat', 'Thur', 'Fri'
    df_plot=df[df['day']== met].sort_values(['time', 'sex'], ascending = False)
    c = next(cols)
    for t in px.box(df_plot, x="time", y="total_bill", color='sex').data:
        r = (i//2)+1
#         print(c)
        fig.add_trace(t.update(showlegend=True if i == 0 else False), row=r, col=c)
            
fig.update_layout(
    boxmode="group", margin={"l": 0, "r": 0, "t": 20, "b": 0}
)#.update_traces(showlegend=True) 

fig.show()

如果您想在此设置中添加任何内容,例如y轴标题,只需添加:

titles = cycle(df['day'].unique())
fig.for_each_yaxis(lambda y: y.update(title = next(titles)))

或者如果我误解了你,你只是想将total_bill添加到yax中,只需使用:

fig.update_yaxes(title = 'total_bill')

匿名用户

  • 最简单的方法是使用facet参数px box
  • 复制您的示例,2行和2行
import plotly.express as px
df = px.data.tips() 
df.loc[df["day"].eq("Sun")]

px.box(df.loc[df["day"].eq("Sun")], x='time', y="total_bill", color="sex",width=600, height=400).show()
px.box(df, x='time', y="total_bill", color="sex", facet_col="day", facet_col_wrap=2, width=600, height=400).show()