Python 在打印为条形图之前,如何在数据框中添加一周中缺少的天数?

Python 在打印为条形图之前,如何在数据框中添加一周中缺少的天数?,python,pandas,Python,Pandas,我有一个数据框,它是船舶执行的不同行程的总结: start_time duration_idle duration_at_power Trip 1 2021-02-01 13:55:35.331 0.828611 1.162222 Trip 2 2021-02-02 07:25:41.574 0.516389 0.927778 Trip 3 2021-02-02 09:46:10.573

我有一个数据框,它是船舶执行的不同行程的总结:

                     start_time duration_idle duration_at_power
Trip 1  2021-02-01 13:55:35.331      0.828611          1.162222
Trip 2  2021-02-02 07:25:41.574      0.516389          0.927778
Trip 3  2021-02-02 09:46:10.573      0.095278            0.1825
Trip 4  2021-02-02 12:45:15.416      0.933611          0.877778
Trip 5  2021-02-02 15:24:45.416      0.298056          1.020833
Trip 6  2021-02-03 07:06:17.665      2.035278          3.190278
Trip 7  2021-02-03 13:15:07.665      0.318611          0.212778
Trip 9  2021-02-04 09:48:59.569      1.025278            0.8325
Trip 10 2021-02-04 14:15:34.569        0.8175          2.068333
Trip 11 2021-02-04 18:21:46.570      0.152778          0.096944
Trip 12 2021-02-05 08:32:26.164      0.292778          1.319722
Trip 13 2021-02-07 08:23:36.930          0.66          0.790556
Trip 14 2021-02-08 07:11:55.395      0.513611          1.662778
Trip 16 2021-02-10 14:48:29.846      0.348056          0.761111
Trip 17 2021-02-12 08:33:30.031      0.737222          1.628611
Trip 18 2021-02-12 13:23:56.530      0.286944          0.443056
Trip 19 2021-02-12 18:33:42.529      0.423611          1.516667
Trip 21 2021-02-15 10:58:31.113      0.667222          0.339444
Trip 23 2021-02-16 11:50:25.271        1.3925          1.330278
Trip 26 2021-02-19 11:47:22.429         0.305          0.551667
Trip 27 2021-02-19 13:30:03.428      0.385833          0.393889
Trip 28 2021-02-19 20:21:59.429      0.304722          1.805556
Trip 29 2021-02-20 08:30:38.109      0.512222          0.250833
Trip 30 2021-02-20 10:01:39.128      0.656389          1.345278
Trip 32 2021-02-22 06:20:30.073      1.192222          1.393333
Trip 33 2021-02-22 10:06:27.074      0.127778          0.155556
Trip 34 2021-02-22 12:57:33.073      0.530278          0.452778
Trip 35 2021-02-23 06:59:40.838      0.369722          1.243333
Trip 36 2021-02-23 10:09:26.837      0.384167          1.151667
Trip 37 2021-02-24 07:57:10.042      1.488056          2.157778
Trip 38 2021-02-24 13:41:00.380      0.328333          0.536944
Trip 39 2021-02-24 16:06:28.380      0.421944          0.880556
Trip 40 2021-02-25 07:32:55.790      0.431944          1.528889
Trip 41 2021-02-25 10:38:04.792      0.189444          0.087778
Trip 42 2021-02-25 11:08:34.791      0.320556              0.05
Trip 43 2021-02-25 13:27:26.793      0.376389          0.796111
Trip 44 2021-02-25 15:38:56.790           0.2          0.222778
Trip 45 2021-02-26 07:39:54.299      0.890278            0.8975
Trip 46 2021-02-26 10:17:45.878      0.271944          0.806389
我将其分为不同的周,然后以条形图的形式绘制给定一天的持续时间总和:

def plot_weeks(df):
    weeks = df.groupby(df["start_time"].dt.week)
    for _, week in weeks:
        week.groupby(week["start_time"].dt.day)[["duration_idle", "duration_at_power"]].sum().plot.bar(stacked=True)
它会生成如下数据帧:

第1周:

            duration_idle  duration_at_power
start_time                                  
1                0.828611           1.162222
2                1.843333           3.008889
3                2.353889           3.403056
4                1.995556           2.997778
5                0.292778           1.319722
7                0.660000           0.790556
第2周:

            duration_idle  duration_at_power
start_time                                  
8                0.513611           1.662778
10               0.348056           0.761111
12               1.447778           3.588333
这会产生如下图:

第1周:

            duration_idle  duration_at_power
start_time                                  
1                0.828611           1.162222
2                1.843333           3.008889
3                2.353889           3.403056
4                1.995556           2.997778
5                0.292778           1.319722
7                0.660000           0.790556

第2周:

            duration_idle  duration_at_power
start_time                                  
8                0.513611           1.662778
10               0.348056           0.761111
12               1.447778           3.588333

然而,我希望使它总是在每周绘图7天,就像第一周。如果有几天没有任何行程,当有一天没有数据时,如何在数据框中自动添加一行

作为一个起点,我认为groupby函数将索引设置为一天的日期时间,而不仅仅是日数可能会很有用,但是我也不确定如何做到这一点。

按照以下步骤进行操作:

  • 开始时间和总和时按天频率重新采样:

  • 请注意,重采样会在 源时段,但不能在最后日期之后执行。 因此,为了得到最后一个7天的绘图,添加这样的“零行”, 要补充上周的数据,源数据中可能有“未完成”:

    dayNo = wrk.index.size
    wrk = wrk.reindex(pd.date_range(start=wrk.index.min(),
        periods=dayNo - (dayNo % -7)), fill_value=0)
    
  • 添加周列(需要按周分组):

  • 为了在x轴上只显示日期(没有时间部分), 将索引类型更改为字符串:

  • 生成绘图:

    for week, grp in wrk.groupby('Week'):
        grp.iloc[:, :2].plot.bar(stacked=True, title=f'Week {week}')
    
    注意
    iloc[:,:2]
    删除“周”(最后一列)

  • 第一周我得到了:

    如您所见,我为每周添加了标题,x标签为 完整日期,而不仅仅是日期

    其他几周自己检查

    我还建议更改列名,至少在wrk中是这样,以获得更多信息 情节图例中的“读者友好”名称

    编辑 我意识到,可能需要同时添加一些“零行” 工作日的开始日期(如果本月在星期一以外的其他日期开始)。 要正确地重新编制wrk索引,即使在上述情况下,也要更改 上述代码发送至:

    # Move back to Monday (if needed)
    d1 = pd.offsets.Week(weekday=0).rollback(wrk.index.min())
    # Move forward to Sunday (if needed)
    d2 = pd.offsets.Week(weekday=6).rollforward(wrk.index.max())
    wrk = wrk.reindex(pd.date_range(start=d1, end=d2), fill_value=0)
    
    它更简洁,不使用datetime模块(Pandas) 它有自己的工具来处理日期,所以不使用是一个好习惯 处理日期/时间的其他模块)

    另请注意,例如,对于2021年5月,扩展日期范围为“2021-04-26” 至“2021-06-06”。它包含42天(6整周),因此 将“初始”天数(31)四舍五入至7的倍数是可行的
    这种情况是错误的。

    我看到了您的数据帧,但没有看到生成图形的代码。我猜你在用matplotlib?我认为这可能是在绘制图表时必须手动执行的操作。您可以为任何matplotlib图形指定x值,因此只需放置七个x插槽,并为彼此设置零entry@QuinnFreedman.plot.bar(stacked=True)代码创建内置于Pandas中的条形图(在后端使用matplotlib)。然而,我会尝试一下,这正是我想要做的。我进行了一次争论,将date_范围行中的开始日期更改为一周的第一天,即索引的最短日期。我是这样做的:start_date=wrk.index.date.min().isocalendar()start_week=start_date[1]start_year=start_date[0]d=str(start_year)+“-W”+str(start_week)重采样_start=datetime.datetime.strtime(d+“-1”,“Y-W%W-%W”)wrk=wrk.reindex(pd.date范围(start=resample\u start,periods=dayNo-(dayNo%-7)),fill\u value=0)感谢您的编辑,它看起来比我的方法干净多了!
    # Move back to Monday (if needed)
    d1 = pd.offsets.Week(weekday=0).rollback(wrk.index.min())
    # Move forward to Sunday (if needed)
    d2 = pd.offsets.Week(weekday=6).rollforward(wrk.index.max())
    wrk = wrk.reindex(pd.date_range(start=d1, end=d2), fill_value=0)