python - Plotly:如何使用 plotly express 为具有多个组的条形图设置动画?

标签 python pandas plotly

我有一个看起来像这样的数据框:
enter image description here
我想要一个用于旧频率和一个用于新频率的条。目前我的图表如下所示:
enter image description here
这是代码的样子:

freq_df['date'] = pd.to_datetime(freq_df['date'])
freq_df['hour'] = freq_df['hour'].astype(str)

fig = px.bar(freq_df, x="hour", y="old freq",hover_name = "date",
  animation_frame= freq_df.date.dt.day)
fig.update_layout(transition = {'duration': 2000})
我如何添加另一个酒吧?
关于DF的说明:
它具有与特定日期中的每个小时相关的频率。
编辑:
一种方法是创建一个类别列并添加旧的和新的频率并在另一个频率列中分配值。我该怎么做:p?
编辑:
这是DF
    ,date,hour,old freq,new freq
43,2020-09-04,18,273,224.0
44,2020-09-04,19,183,183.0
45,2020-09-04,20,99,111.0
46,2020-09-04,21,130,83.0
47,2020-09-04,22,48,49.0
48,2020-09-04,23,16,16.0
49,2020-09-05,0,8,6.0
50,2020-09-05,1,10,10.0
51,2020-09-05,2,4,4.0
52,2020-09-05,3,7,7.0
53,2020-09-05,4,25,21.0
54,2020-09-05,5,114,53.0
55,2020-09-05,6,284,197.0
56,2020-09-05,7,343,316.0
57,2020-09-05,8,418,419.0
58,2020-09-05,9,436,433.0
59,2020-09-05,10,469,396.0
60,2020-09-05,11,486,300.0
61,2020-09-05,12,377,140.0
62,2020-09-05,13,552,103.0
63,2020-09-05,14,362,117.0
64,2020-09-05,15,512,93.0
65,2020-09-05,16,392,41.0
66,2020-09-05,17,268,31.0
67,2020-09-05,18,223,30.0
68,2020-09-05,19,165,24.0
69,2020-09-05,20,195,15.0
70,2020-09-05,21,90,
71,2020-09-05,22,46,1.0
72,2020-09-05,23,17,1.0

最佳答案

分两步回答:
1. 使用 pd.wide_to_long 对您的数据进行轻微转换:

df_long = pd.wide_to_long(freq_df, stubnames='freq',
                          i=['date', 'hour'], j='type',
                          sep='_', suffix='\w+').reset_index()
2. 使用以下方法绘制两组条形轨迹:
fig1 = px.bar(df_long, x='hour', y = 'freq', hover_name = "date", color='type',
            animation_frame= 'date', barmode='group')
这是第一帧的结果:
enter image description here
这是运行动画时第二帧的结果:
enter image description here

细节:
如果我正确理解您的问题,您想为条形图制作动画,其中您的两个频率每小时都有一个条形freq_oldfreq_new像这样:
enter image description here
如果是这种情况,那么您的样本数据就不好了,因为您的动画标准是 hourdate而你只有 2020-09-04 的观察(小时)然后是 2020-09-05 的 24 个观察值.但别担心,既然你的问题引起了我的兴趣,我也制作了一些示例数据,这些数据实际上会按照你希望的方式工作。
唯一真正的挑战是px.bar不接受y= [freq_old, freq_new] ,或类似的东西,为您构建两个不同类别的酒吧系列。但是你可以 制作 px.bar通过提供 color 建立两组酒吧争论。
但是,您需要一列来标识您的不同 freqs像这样:
0    new
1    old
2    new
3    old
4    new
5    old
6    new
7    old
8    new
9    old
换句话说,您必须将最初具有宽格式的数据帧转换为长格式,如下所示:
    date        hour    type    day freq
0   2020-01-01  0       new     1   7.100490
1   2020-01-01  0       old     1   2.219932
2   2020-01-01  1       new     1   7.015528
3   2020-01-01  1       old     1   8.707323
4   2020-01-01  2       new     1   7.673314
5   2020-01-01  2       old     1   2.067192
6   2020-01-01  3       new     1   9.743495
7   2020-01-01  3       old     1   9.186109
8   2020-01-01  4       new     1   3.737145
9   2020-01-01  4       old     1   4.884112
这就是这个片段的作用:
df_long = pd.wide_to_long(freq_df, stubnames='freq',
                          i=['date', 'hour'], j='type',
                          sep='_', suffix='\w+').reset_index()
stubnames使用前缀来标识您想要堆叠为长格式的列。这就是我重命名 new_freq 的原因和 old_freqfreq_newfreq_old , 分别。 j='type'只需使用 sep='_' 获取类别名称的最后一部分并生成我们需要告诉彼此频率的列:
type
old
new
old
...
suffix='\w+'告诉 pd.wide_to_long我们使用非整数作为后缀。
就是这样!
完整代码:
# imports
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
import random

# sample data
observations = 24*5
np.random.seed(5); cols = list('a')
freq_old = np.random.uniform(low=-1, high=1, size=observations).tolist()
freq_new = np.random.uniform(low=-1, high=1, size=observations).tolist()
date = [t[:10] for t in pd.date_range('2020', freq='H', periods=observations).format()]
hour = [int(t[11:13].lstrip()) for t in pd.date_range('2020', freq='H', periods=observations).format()]

# sample dataframe of a wide format such as yours
freq_df=pd.DataFrame({'date': date, 
                'hour':hour,
                 'freq_new':freq_new,
                 'freq_old':freq_old})
freq_df['day']=pd.to_datetime(freq_df['date']).dt.day

# attempt to make my random data look a bit
# like your real world data.
# but don't worry too much about that...
freq_df.freq_new = abs(freq_df.freq_new.cumsum())
freq_df.freq_old = abs(freq_df.freq_old.cumsum())

# sample dataframe of a long format that px.bar likes
df_long = pd.wide_to_long(freq_df, stubnames='freq',
                          i=['date', 'hour'], j='type',
                          sep='_', suffix='\w+').reset_index()

# plotly express bar chart with multiple bar groups.
fig = px.bar(df_long, x='hour', y = 'freq', hover_name = "date", color='type',
            animation_frame= 'date', barmode='group')

# set up a sensible range for the y-axis
fig.update_layout(yaxis=dict(range=[df_long['freq'].min()*0.8,df_long['freq'].max()*1.2]))
fig.show()

关于python - Plotly:如何使用 plotly express 为具有多个组的条形图设置动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63780291/

相关文章:

python - 从一对行的列表到一个平面的行列表

python - 如何使用一个数组的索引来定义另一个数组的 __getitem__ ?

Python(Pandas)在指定条件下更新前 x 行

python - 当并非所有单元格都包含该分隔符时,删除分隔符之前的所有内容

python - 绘制两个重叠的漏斗 : the code isn't working

python - Plotly-Dash:如何过滤具有多个数据框列的仪表板?

python - 是否有一致的方法来枚举两个日期之间的天数/周数/月数?

python - 根据 Python 中的数组值拆分数组

python - 如何将多索引更改为平面列名

python - 值错误 : Invalid element(s) received for the 'data' property