plotly 中的饼图下拉列表 Python

Piechart dropdown in plotly Python

我有这样大的 df(这些数据只是一个例子):

|Category|Sign|
|-       |-|
|One     |-|
|Two     |+|
|One     |-|
|Two     |-|
|One     |+|

我必须用 plotly 做饼图 - 对于每个类别,我必须计算“+”和“-”(这很简单,我做到了),然后插入一个下拉列表来选择其中的一个(在这个情况 2) 将显示饼图。我有这样的东西:

cat = set(data['Category'])
for c in cat:
    t = data[data['Category'] == c]
    c = t['Sign'].value_counts()
    fig = px.pie(t, values = c.values, names = c.index)
    fig.show()

现在我不知道如何做这个下拉菜单 - 有人可以帮我吗? :) 或者指导我怎么做?

  • 核心概念:所有痕迹都需要是同一个图形的一部分才能用updatemenus
  • 控制
  • 已生成数据,因为它更易于测试概念(更多类别)
  • 以与您相同的方式为每个类别创建了数字。但是,将它们放在 dict
  • 中会更方便
  • dict中的所有数字合并为一个consolidate figure
  • 最终构建 updatemenus 以满足您的要求
import numpy as np
import plotly.express as px

# generate data matching definition in question
data = pd.DataFrame(
    {
        "Category": np.random.choice(["One", "Two", "Three"], 100),
        "Sign": np.random.choice(list("+-"), 100),
    }
)

# simplify - use value_counts() on whole dataframe
df_vc = data.value_counts()
# create a figure for each category
figs = {
    c: px.pie(df_vc.loc[c].reset_index(), values=0, names="Sign").update_traces(
        name=c, visible=False
    )
    for c in df_vc.index.get_level_values("Category").unique()
}

# integrate figures per category into one figure
defaultcat = df_vc.index.get_level_values("Category").unique()[0]
fig = figs[defaultcat].update_traces(visible=True)
for k in figs.keys():
    if k != defaultcat:
        fig.add_traces(figs[k].data)

# finally build dropdown menu
fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "label": k,
                    "method": "update",
                    # list comprehension for which traces are visible
                    "args": [{"visible": [kk == k for kk in figs.keys()]}],
                }
                for k in figs.keys()
            ]
        }
    ]
)

补充更新

  • 在下拉菜单中包含类别组合
  • 扩展 dict 的构建以包含组合
import itertools
figs = {
    **{
        c: px.pie(df_vc.loc[c].reset_index(), values=0, names="Sign").update_traces(
            name=c, visible=False
        )
        for c in df_vc.index.get_level_values("Category").unique()
    },
    **{
        f"{a}-{b}": px.pie(
            df_vc.loc[[a, b]].reset_index(), values=0, names="Sign"
        ).update_traces(name=f"{a}-{b}", visible=False)
        for a, b in itertools.combinations(
            df_vc.index.get_level_values("Category").unique(), 2
        )
    },
}