pandas dataframe sum date range of another DataFrame

Viewed 367

I have two dataframes. I want to sum an "amount" column in the 2nd, for each record in the first datafame.

So for each

df1.Date = sum(df2.amount WHERE df1.Date <= df2.Date AND df1.yearAgo >= df2.Date)

df1 = pd.DataFrame({'Date':['2018-10-31','2018-10-30','2018-10-29','2018-10-28'],'yearAgo':['2017-10-31','2017-10-30','2017-10-29','2017-10-28']})

df2 = pd.DataFrame({'Date':['2018-10-30','2018-7-30','2018-4-30','2018-1-30','2017-10-30'],'amount':[1.0,1.0,1.0,1.0,0.75]})

desired results:

df1.Date     yearToDateTotalAmount
2018-10-31        3.0
2018-10-30        4.75
2018-10-29        3.75
2018-10-28        3.75
1 Answers

IIUC, your expected output should have 4 in first row.

You can achieve this very efficiently using numpy's feature of outer comparison, since less_equal and greater_equal are ufuncs.

Notice that

>>> np.greater_equal.outer(df1.Date, df2.Date)

array([[ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True],
       [False,  True,  True,  True,  True],
       [False,  True,  True,  True,  True]])

So you can get your mask by

mask = np.greater_equal.outer(df1.Date, df2.Date) & 
       np.less_equal.outer(df1.yearAgo, df2.Date)

And use outer multiplication + summing along axis=1

>>> np.sum(np.multiply(mask, df2.amount.values), axis=1)

Out[49]:
array([4.  , 4.75, 3.75, 3.75])

In the end, just assign back

>>> df1['yearToDateTotalAmount'] = np.sum(np.multiply(mask, df2.amount.values), axis=1)

    Date        yearAgo     yearToDateTotalAmount
0   2018-10-31  2017-10-31  4.00
1   2018-10-30  2017-10-30  4.75
2   2018-10-29  2017-10-29  3.75
3   2018-10-28  2017-10-28  3.75
Related