Search code examples
pythonpandasdata-processing

How to get cumulative sum of unique IDs with group by?


I am very new to python and pandas working on a pandas dataframe which looks like

Date     Time           ID   Weight
Jul-1     12:00         A       10
Jul-1     12:00         B       20
Jul-1     12:00         C       100
Jul-1     12:10         C       100
Jul-1     12:10         D       30
Jul-1     12:20         C       100
Jul-1     12:20         D       30
Jul-1     12:30         A       10
Jul-1     12:40         E       40
Jul-1     12:50         F       50
Jul-1     1:00          A       40

I am trying to achieve group by date, Time and ids and apply cumulative sum such that if an id is present in the next time-slot the weight is only added once(uniquely). The resulting data frame would look like this

Date     Time           Weight   
Jul-1     12:00         130     (10+20+100)
Jul-1     12:10         160     (10+20+100+30)
Jul-1     12:20         160     (10+20+100+30)
Jul-1     12:30         160     (10+20+100+30)
Jul-1     12:40         200     (10+20+100+30+40)
Jul-1     12:50         250     (10+20+100+30+40+50)
Jul-1     01:00         250     (10+20+100+30+40+50)

This is what I tried below, however this is still counting the weights multiple times:

df=df.groupby(['date','time','ID'])['Wt'].apply(lambda x: x.unique().sum()).reset_index()
df['cumWt']=df['Wt'].cumsum()

Any help would be really appreciated!

Thanks a lot in advance!!


Solution

  • The code below uses pandas.duplicate(), pandas.merge(), pandas.groupby/sum and pandas.cumsum() to come to the desired output:

    # creates a series of weights to be considered and rename it to merge
    unique_weights = df['weight'][~df.duplicated(['weight'])]
    unique_weights.rename('consider_cum', inplace = True)
    
    # merges the series to the original dataframe and replace the ignored values by 0
    df = df.merge(unique_weights.to_frame(), how = 'left', left_index=True, right_index=True)
    df.consider_cum = df.consider_cum.fillna(0)
    
    # sums grouping by date and time
    df = df.groupby(['date', 'time']).sum().reset_index()
    
    # create the cumulative sum column and present the output
    df['weight_cumsum'] = df['consider_cum'].cumsum()
    df[['date', 'time', 'weight_cumsum']]
    

    Produces the following output:

    enter image description here