首页 > 解决方案 > 如何对 GroupBy 和连续日期条件下的值求和?

问题描述

给定表:

ID 线 地点 日期 单位 全部的
1 X AAA 2017 年 5 月 2 日 12 30
2 X AAA 2017 年 5 月 3 日 10 22
3 X AAA 2017 年 5 月 4 日 22 40
4 Z AAA 2017 年 5 月 20 日 15 44
5 Z AAA 2017 年 5 月 21 日 8 30
6 Z BBB 2017 年 5 月 22 日 10 32
7 Z BBB 2017 年 5 月 23 日 25 52
8 ķ CCC 2017 年 6 月 2 日 6 22
9 ķ CCC 2017 年 6 月 3 日 4 33
10 ķ CCC 2017 年 8 月 12 日 11 44
11 ķ CCC 2017 年 8 月 13 日 19 40
12 ķ CCC 2017 年 8 月 14 日 30 40

对于每一行,如果 ID,LINE ,SITE 等于前一行(天)需要计算如下(最后一天)和(最后 3 天):请注意,需要确保日期在 ID,LINE 的“groupby”下是连续的,网站栏目

ID 线 地点 日期 单位 全部的 最后一天 过去 3 天
1 X AAA 2017 年 5 月 2 日 12 30 0 0
2 X AAA 2017 年 5 月 3 日 10 22 12/30 12/30
3 X AAA 2017 年 5 月 4 日 22 40 10/22 (10+12)/(30+22)
4 Z AAA 2017 年 5 月 20 日 15 44 0 0
5 Z AAA 2017 年 5 月 21 日 8 30 15/44 15/44
6 Z BBB 2017 年 5 月 22 日 10 32 0 0
7 Z BBB 2017 年 5 月 23 日 25 52 10/32 10/32
8 ķ CCC 2017 年 6 月 2 日 6 22 0 0
9 ķ CCC 2017 年 6 月 3 日 4 33 6/22 6/22
10 ķ CCC 2017 年 8 月 12 日 11 44 4/33 0
11 ķ CCC 2017 年 8 月 13 日 19 40 11/44 (11/44)
12 ķ CCC 2017 年 8 月 14 日 30 40 19/40 (11+19/44+40)

标签: pandasdatepandas-groupbyshiftcumsum

解决方案


在这种情况下,我通常使用 groupby 进行 for 循环:

import pandas as pd
import numpy as np

#copied your table
table = pd.read_csv('/home/fm/Desktop/stackover.csv')
table.set_index('ID', inplace = True)
table[['Last day','Last 3 days']] = np.nan

for i,r in table.groupby(['LINE' ,'SITE']):
    #First subset non sequential dates
    limits_interval = pd.to_datetime(r['DATE']).diff() != '1 days'
    #First element is a false positive, as its impossible to calculate past days from first day
    limits_interval.iloc[0]=False

    ids_subset = r.index[limits_interval].to_list()
    ids_subset.append(r.index[-1]+1) #to consider all values
    id_start = 0

    for id_end in ids_subset:    
        r_sub = r.loc[id_start:id_end-1, :].copy()
        id_start = id_end 

        #move all values one day off, if the database is as in your example (1 line per day) wont have problems
        r_shifted = r_sub.shift(1)

        r_sub['Last day']=r_shifted['UNITS']/r_shifted['TOTAL']

        aux_units_cumsum = r_shifted['UNITS'].cumsum()
        aux_total_cumsum = r_shifted['TOTAL'].cumsum()

        r_sub['Last 3 days'] = aux_units_cumsum/aux_total_cumsum

        r_sub.fillna(0, inplace = True)

        table.loc[r_sub.index,:]=r_sub.copy()

您可以创建一个函数并在 groupby 中应用,它会更干净:Apply function to pandas groupby。它会更优雅。希望我能帮助你,祝你好运


推荐阅读