【问题标题】:Creating a dropdown to filter by date month (pandas + plotly)创建一个按日期月份过滤的下拉列表(pandas + plotly)
【发布时间】:2021-10-12 23:53:42
【问题描述】:

DataFrame

Current_Graph

我是否可以在此条形图上集成一个下拉框,为一年中的每个月提供 12 个选项。选择一个月后,会过滤该月的数据并连续更新绘图图以仅显示所选月份的条形?

【问题讨论】:

    标签: python pandas jupyter-notebook plotly


    【解决方案1】:
    • 具有与数据框结构相匹配的模拟数据
    • 您可以构建 updatemenus 按钮来设置 xaxis 范围。通过在列表理解中构建另一个包含要执行此操作的数据的数据框来动态完成此操作
    import numpy as np
    import pandas as pd
    import plotly.express as px
    
    # simulate data
    df = pd.DataFrame({"Date": pd.date_range("1-jun-2020", "now")}).pipe(
        lambda d: d.assign(**{"Time Per Ball (Seconds)": np.random.uniform(20, 51, len(d))})
    )
    
    fig = px.bar(df, x="Date", y="Time Per Ball (Seconds)")
    
    dfbut = (
        (df["Date"] + pd.offsets.MonthBegin(-1))
        .drop_duplicates()
        .to_frame()
        .assign(
            label=lambda d: d["Date"].dt.strftime("%b-%Y"),
            start=lambda d: (d["Date"] - pd.Timestamp("1970-01-01")) // pd.Timedelta("1ms"),
            end=lambda d: d["start"].shift(-1),
        )
        .fillna((df["Date"].max() - pd.Timestamp("1970-01-01")) // pd.Timedelta("1ms"))
    )
    
    # build buttons to filter by month
    fig.update_layout(
        updatemenus=[
            {
                "buttons": [
                    {
                        "label": r[1]["label"],
                        "method": "relayout",
                        "args": [{"xaxis": {"range": [r[1]["start"], r[1]["end"]]}}],
                    }
                    for r in dfbut.iterrows()
                ]
            },
            {"buttons":[{"label":"All data", "method":"relayout","args":[{"xaxis":{"range":[]}}]}],"y":.8,"type":"buttons"}
        ]
    )
    
    

    使用多条轨迹的方法

    • 每个月都有一个跟踪。 dfdfbut 构建完成后运行新单元
    • 在更新菜单中设置跟踪的可见性
    • 还使用 uirevision{"xaxis": {"autorange": True} 来维护视图切换之间的布局
    # add EndDate to make next part simpler
    dfbut = dfbut.assign(EndDate=dfbut["Date"].shift(-1) - pd.Timedelta(days=1)).fillna(df["Date"].max())
    dfbut = dfbut.loc[~(dfbut["EndDate"] < df["Date"].min())]
    
    # create a trace per month so zoom / pan is maintained between selections
    go.Figure(
        [
            px.bar(
                df.loc[df["Date"].between(start, end)],
                x="Date",
                y="Time Per Ball (Seconds)",
            )
            .update_traces(name=label)
            .data[0]
            for label, start, end in dfbut.loc[:, ["label", "Date", "EndDate"]].values
        ]
    ).update_layout(
        updatemenus=[
            {
                "buttons": [
                    {
                        "label": "All",
                        "method": "update",
                        "args": [
                            {"visible": (dfbut["label"] == dfbut["label"]).tolist()},
                            {"xaxis": {"autorange": True}},
                        ],
                    }
                ]
                + [
                    {
                        "label": l,
                        "method": "update",
                        "args": [
                            {"visible": (dfbut["label"] == l).tolist()},
                            {"xaxis": {"autorange": True}},
                        ],
                    }
                    for l in dfbut["label"]
                ]
            }
        ],
        xaxis={"autorange": True},
    )
    

    【讨论】:

    • 不过谢谢你,我刚刚尝试将其粘贴到 jupyter 并收到以下错误:'TypeError: cannot astype a datetimelike from [datetime64[ns]] to [int32]'跨度>
    • 熊猫 1.3.1,情节 5.1.0。我怀疑是熊猫版本问题
    • 我已将我的 pandas 更新到 1.3.1 并 plotly 到 5.1.0,但同样的问题仍然存在。它似乎来自第 23 行。
    • 我重新设计了 dfbut 数据框的构建方式。从不喜欢留下警告
    • 是否可以将其配置为使用来自 datetime 模块的 python 内置,即 datetime.time、datetime.date、datetime.timedelta,而不是 pandas?我发现它们不兼容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多