【问题标题】:In a Plotly histogram, how to make each animation frame a row in the dataframe?在 Plotly 直方图中,如何使每个动画帧在数据帧中排成一行?
【发布时间】:2021-07-25 11:30:02
【问题描述】:

我有以下熊猫数据框:

       month  stories  comments  comment_authors  story_authors
0    2006-10       49        12                4             16
1    2007-02      564       985              192            163
2    2007-03     1784      4521              445            287

我正在尝试构建一个 Plotly 直方图,其中每个 storiescommentscomment_authorsstory_authors 列有四个分类箱(x 轴),以及计数(y-轴)是特定month(即特定行)的给定数量。然后,我尝试使用 animation_frameanimation_groupPlotly Express 中根据月份对直方图进行动画处理。

例如,month=2006-10 的第一个直方图如下所示:

50 |  ____
45 | |    |
40 | |    |
35 | |    |
30 | |    |
25 | |    |
20 | |    |
15 | |    |                               ____
10 | |    |    ____                      |    |
 5 | |    |   |    |    ______           |    |
 0  ----------------------------------------------------
     stories  comments  comment_authors  story_authors

在下一个动画帧的直方图中,它将从storiescommentscomment_authorsstory_authors 列中读取month=2007-02 的值。

这可以在 Plotly 中构建吗?有没有比px.Histogram 更好的数字,比如px.Bar?我尝试将列放在 x 轴上并使用动画帧的月份,但这会将列堆叠到直方图上的一个 bin 中并使用整个列的计数,而不是特定行的值。

histogram = dcc.Graph(figure=px.histogram(
    df, x=['stories', 'comments', 'comment_authors', 'story_authors'],
    animation_frame='month', animation_group='month'
))

【问题讨论】:

    标签: python pandas plotly plotly-python


    【解决方案1】:

    无法使用您呈现的数据绘制直方图。您可以做的最好的事情是条形图,您可以使用时间序列对其进行动画处理。我已经修改了官方reference 中的示例以适合您的数据。

    import pandas as pd
    import numpy as np
    import io
    
    data = '''
          month  stories  comments  comment_authors  story_authors
    0    2006-10       49        12                4             16
    1    2007-02      564       985              192            163
    2    2007-03     1784      4521              445            287
    '''
    
    df = pd.read_csv(io.StringIO(data), delim_whitespace=True)
    df.set_index('month', inplace=True)
    dfs = df.unstack().reset_index()
    dfs.columns = ['category', 'month', 'value']
    import plotly.express as px
    
    fig = px.bar(dfs, x='category', y='value', color='category', animation_frame='month', range_y=[0,dfs['value'].max()])
    
    fig.show()
    

    【讨论】:

    • 谢谢,这比我的手动方法简单得多
    【解决方案2】:

    @r-beginners 的回答是最好的方法,但我想分享如何手动完成,以防其他人将来发现这个问题(这样我的辛劳就不会浪费了)。这是我在@r-beginners 回答之前手动完成此操作的方法。

    # build list of frames for animation
    cols = ['stories', 'comments', 'comment_authors', 'story_authors']
    frames = list(map(
        lambda index: go.Frame(
            data=[go.Bar(
                x=cols,
                y=list(map(lambda col: df.iloc[index][col], cols))
            )]
        ), range(len(df.index))
    ))
    
    # compute chart height
    m = max(list(filter(
        lambda m: not isinstance(m, str), list(df.max())
    ))) * 1.1
    
    # compute animation steps for slider
    steps = list(map(
        lambda index: {
            'args': [
                [str(df.iloc[index]['month'])],
                {
                    'frame': {'duration': 300, 'redraw': False},
                    'mode': 'immediate',
                    'transition': {'duration': 300}
                }
            ],
            'label': str(df.iloc[index]['month']),
            'method': 'animate'
        }, range(len(df.index))
    ))
    
    # metadata for slider element
    sliders_dict = {
        "active": 0,
        "yanchor": "top",
        "xanchor": "left",
        "currentvalue": {
            "font": {"size": 20},
            "prefix": "Month: ",
            "visible": True,
            "xanchor": "right"
        },
        "transition": {"duration": 300, "easing": "cubic-in-out"},
        "pad": {"b": 10, "t": 50},
        "len": 0.9,
        "x": 0.1,
        "y": 0,
        "steps": steps
    }
    
    # histogram figure - actually a bar chart
    histogram = dcc.Graph(id='counts-histogram', figure=go.Figure(
        data=frames[0].data[0],
        layout=go.Layout(
            yaxis=dict(range=[0, m], autorange=False),
            updatemenus=[
                {
                    "buttons": [
                        {
                            "args": [None, {"frame": {"duration": 500, "redraw": False},
                                            "fromcurrent": True, "transition": {"duration": 300,
                                                                                "easing": "quadratic-in-out"}}],
                            "label": "Play",
                            "method": "animate"
                        },
                        {
                            "args": [[None], {"frame": {"duration": 0, "redraw": False},
                                              "mode": "immediate",
                                              "transition": {"duration": 0}}],
                            "label": "Pause",
                            "method": "animate"
                        }
                    ],
                    "direction": "left",
                    "pad": {"r": 10, "t": 87},
                    "showactive": False,
                    "type": "buttons",
                    "x": 0.1,
                    "xanchor": "right",
                    "y": 0,
                    "yanchor": "top"
                }
            ],
            sliders = [sliders_dict]
        ),
        frames=frames
    ))
    

    【讨论】:

      猜你喜欢
      • 2018-07-10
      • 1970-01-01
      • 1970-01-01
      • 2017-12-18
      • 1970-01-01
      • 2020-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多