按组在日期范围内高效滚动聚合-Python 2.7 Windows-pandas 0.19.2

按组在日期范围内高效滚动聚合-Python 2.7 Windows-pandas 0.19.2,python,pandas,numpy,Python,Pandas,Numpy,我试图找到一种有效的方法,在给定分组和日期范围的情况下生成滚动计数或总和。最终,我希望能够添加条件,即评估“类型”字段,但我还没有做到这一点。我写了一些东西来完成这项工作,但我觉得可以有一种更直接的方式来达到预期的结果 我的pandas数据框目前看起来是这样的,期望的输出放在最后一列“rolling_sales_180”中 name date amount rolling_sales_180 0 David 2015-01-01 100

我试图找到一种有效的方法,在给定分组和日期范围的情况下生成滚动计数或总和。最终,我希望能够添加条件,即评估“类型”字段,但我还没有做到这一点。我写了一些东西来完成这项工作,但我觉得可以有一种更直接的方式来达到预期的结果

我的pandas数据框目前看起来是这样的,期望的输出放在最后一列“rolling_sales_180”中

    name       date  amount  rolling_sales_180
0  David 2015-01-01     100              100.0
1  David 2015-01-05     500              600.0
2  David 2015-05-30      50              650.0
3  David 2015-07-25      50              100.0
4   Ryan 2014-01-04     100              100.0
5   Ryan 2015-01-19     500              500.0
6   Ryan 2016-03-31      50               50.0
7    Joe 2015-07-01     100              100.0
8    Joe 2015-09-09     500              600.0
9    Joe 2015-10-15      50              650.0
我当前的解决方案和环境可以在下面找到。我一直在根据stackoverflow中的R Q&A对我的解决方案进行建模

将熊猫作为pd导入
将numpy作为np导入
def trans_date_to_dist_矩阵(日期列):#用于创建距离矩阵
x=日期_col.tolist()
y=日期_col.tolist()
数据=[]
对于x中的i:
tmp=[]
对于y中的j:
附加tmp(绝对值((i-j.天))
data.append(tmp)
德尔tmp
返回pd.DataFrame(数据=数据,索引=日期列值,列=日期列值)
def lower_tri(x_col,date_col,win):#x_col=列用户希望滚动求和,date_col=日期,win=时间窗口
dm=传输日期到距离矩阵(日期列=日期列)#dm=距离矩阵
dm=dm。其中(dm=0.0]=1.0#清除较低的tri,以便我们可以对评估当天发生的事件求和
lt=lt.fillna(0)#将NaN替换为0进行乘法运算
返回pd.DataFrame(x_col.values*lt.values).sum(axis=1).tolist()
def展平(x):
尝试:
n=[v代表sl,x代表sl中的v]
返回[v代表sl,n代表sl中的v]
除:
返回[v代表sl,x代表sl中的v]
数据=[
[David',1/1/2015',100],[David',1/5/2015',500],[David',5/30/2015',50],[David',7/25/2015',50],
['Ryan','2014年4月1日',100],'Ryan','2015年1月19日',500],'Ryan','2016年3月31日',50],
[Joe',7/1/2015',100],“Joe”,“9/9/2015',500],“Joe”,“10/15/2015',50]
]
列表的值=[]
日期\u df=pd.DataFrame(数据=数据,列=['name','date','amount'],索引=无)
dates_df['date']=pd.to_datetime(dates_df['date'])
附加(日期为groupby('name',因为索引=False)。应用(
lambda x:lower_tri(x_col=x.amount,date_col=x.date,win=180)))
新数据=展平(VAL列表)
日期_df['rolling_sales_180']=新的_数据
打印日期
感谢您的时间和反馈。

Pandas支持通过该方法,因此您可以使用该方法,而不是从头开始编写自己的解决方案:

def get_rolling_amount(grp, freq):
    return grp.rolling(freq, on='date')['amount'].sum()

df['rolling_sales_180'] = df.groupby('name', as_index=False, group_keys=False) \
                            .apply(get_rolling_amount, '180D')
结果输出:

    name       date  amount  rolling_sales_180
0  David 2015-01-01     100              100.0
1  David 2015-01-05     500              600.0
2  David 2015-05-30      50              650.0
3  David 2015-07-25      50              100.0
4   Ryan 2014-01-04     100              100.0
5   Ryan 2015-01-19     500              500.0
6   Ryan 2016-03-31      50               50.0
7    Joe 2015-07-01     100              100.0
8    Joe 2015-09-09     500              600.0
9    Joe 2015-10-15      50              650.0

你确定“rolling_sales_180”的样本输出是正确的吗?该列应该是180个滚动总和,对吗?Ryan的所有日期都相隔一年多,但它们仍然在求和?而Joe的所有日期都在180天之内,并且没有求和?你是否以某种方式切换了这两个日期?@root-我可能转换不正确-我很抱歉。不用担心,只是确保我对问题的理解是正确的。@JohnE-我做了一些与groupby和rolling相关的研究,但一切似乎都与偶数序列的时间序列数据有关。我没有看到任何类似于下面建议的解决方案。Ryan的Rollins\u sales\u 180值应该是100、500和50。这是这是一个很好的解决方案。感谢您对时间感知滚动的了解。我过去使用过滚动方法,但从未使用过这种方法。在应用函数内部进行变异实际上是非惯用的。您还可以使用更直接的语法:将默认参数指定为。groupby有点困难distracting@Jeff:我尝试使用直接方法:
df.groupby('name').rolling('180D',on='date')['amount'].sum()
但是得到一个错误
ValueError:date必须是单调的
。这是预期的吗?还是我的语法错误?我意识到日期作为一个整体不是单调的,但在每个组中都是。首先按日期排序似乎没有帮助。
    name       date  amount  rolling_sales_180
0  David 2015-01-01     100              100.0
1  David 2015-01-05     500              600.0
2  David 2015-05-30      50              650.0
3  David 2015-07-25      50              100.0
4   Ryan 2014-01-04     100              100.0
5   Ryan 2015-01-19     500              500.0
6   Ryan 2016-03-31      50               50.0
7    Joe 2015-07-01     100              100.0
8    Joe 2015-09-09     500              600.0
9    Joe 2015-10-15      50              650.0