Python 基于滚动周期的上一行的最大值
我的数据集如下:Python 基于滚动周期的上一行的最大值,python,pandas,rolling-computation,Python,Pandas,Rolling Computation,我的数据集如下: data = pd.DataFrame({ 'ID': ['27459', '27459', '27459', '27459', '27459', '27459', '27459', '48002', '48002', '48002'], 'Invoice_Date': ['2020-06-26', '2020-06-29', '2020-06-30', '2020-07-14', '2020-07-25',
data = pd.DataFrame({
'ID': ['27459', '27459', '27459', '27459', '27459', '27459', '27459', '48002', '48002', '48002'],
'Invoice_Date': ['2020-06-26', '2020-06-29', '2020-06-30', '2020-07-14', '2020-07-25',
'2020-07-30', '2020-08-02', '2020-05-13', '2020-06-20', '2020-06-28'],
'Payment_Term': [7,8,3,6,4,7,8,5,3,6],
'Payment_Date': ['2020-07-05', '2020-07-05','2020-07-03', '2020-07-21', '2020-07-31',
'2020-08-15', '2020-08-22', '2020-06-16', '2020-06-23', '2020-07-05'],
'Due_Date': ['2020-07-03', '2020-07-07', '2020-07-03', '2020-07-20', '2020-07-29',
'2020-08-06', '2020-08-10', '2020-05-18', '2020-06-23', '2020-07-04'],
'Delay': [2,-2,0,1,2,9,12,29,0,1],
'Difference_Date': [0,3,1,14,11,5,3,0,38,8],
})
data
我需要添加另一列Max
,该列显示上一行Delay
的最大值。它将有另一个条件,即,它应该是一个30天的滚动期。这意味着,对于当前行中的Max
,将采用前一行中的最大延迟,即从当前行发票日期起30天内的延迟
所需的输出为:
ID Invoice_Date Payment_Term Payment_Date Due_Date Delay Difference_Date Max
27459 2020-06-26 7 2020-07-05 2020-07-03 2 0 0
27459 2020-06-29 8 2020-07-05 2020-07-07 -2 3 2
27459 2020-06-30 3 2020-07-03 2020-07-03 0 1 2
27459 2020-07-14 6 2020-07-21 2020-07-20 1 14 2
27459 2020-07-25 4 2020-07-31 2020-07-29 2 11 2
27459 2020-07-30 7 2020-08-15 2020-08-06 9 5 2
27459 2020-08-02 8 2020-08-22 2020-08-10 12 3 9
48002 2020-05-13 5 2020-06-16 2020-05-18 29 0 0
48002 2020-06-20 3 2020-06-23 2020-06-23 0 38 29
48002 2020-06-28 6 2020-07-05 2020-07-04 1 8 29
一种可能的方法是:
data['Invoice_Date'] = pd.to_datetime(data['Invoice_Date'])
groups = data.groupby('ID')
for group_name, df_group in groups:
for idx,row in df_group.iterrows():
dt_range = pd.date_range(row['Invoice_Date'] - pd.to_timedelta(30, 'day'), row['Invoice_Date'])[:-1]
data.loc[idx, 'max'] = df_group[df_group.Invoice_Date.isin(dt_range)].Delay.max()
print(data)
输出:
ID Invoice_Date Payment_Term Payment_Date Due_Date Delay Difference_Date max
0 27459 2020-06-26 7 2020-07-05 2020-07-03 2 0 NaN
1 27459 2020-06-29 8 2020-07-05 2020-07-07 -2 3 2.0
2 27459 2020-06-30 3 2020-07-03 2020-07-03 0 1 2.0
3 27459 2020-07-14 6 2020-07-21 2020-07-20 1 14 2.0
4 27459 2020-07-25 4 2020-07-31 2020-07-29 2 11 2.0
5 27459 2020-07-30 7 2020-08-15 2020-08-06 9 5 2.0
6 27459 2020-08-02 8 2020-08-22 2020-08-10 12 3 9.0
7 48002 2020-05-13 5 2020-06-16 2020-05-18 29 0 NaN
8 48002 2020-06-20 3 2020-06-23 2020-06-23 0 38 NaN
9 48002 2020-06-28 6 2020-07-05 2020-07-04 1 8 0.0
您可以使用数据填充NAN。fillna(0)
。请查看ID“48002”的第一个值是否为NaN,因为之前的值不在30天范围内。一种可能的方法:
data['Invoice_Date'] = pd.to_datetime(data['Invoice_Date'])
groups = data.groupby('ID')
for group_name, df_group in groups:
for idx,row in df_group.iterrows():
dt_range = pd.date_range(row['Invoice_Date'] - pd.to_timedelta(30, 'day'), row['Invoice_Date'])[:-1]
data.loc[idx, 'max'] = df_group[df_group.Invoice_Date.isin(dt_range)].Delay.max()
print(data)
输出:
ID Invoice_Date Payment_Term Payment_Date Due_Date Delay Difference_Date max
0 27459 2020-06-26 7 2020-07-05 2020-07-03 2 0 NaN
1 27459 2020-06-29 8 2020-07-05 2020-07-07 -2 3 2.0
2 27459 2020-06-30 3 2020-07-03 2020-07-03 0 1 2.0
3 27459 2020-07-14 6 2020-07-21 2020-07-20 1 14 2.0
4 27459 2020-07-25 4 2020-07-31 2020-07-29 2 11 2.0
5 27459 2020-07-30 7 2020-08-15 2020-08-06 9 5 2.0
6 27459 2020-08-02 8 2020-08-22 2020-08-10 12 3 9.0
7 48002 2020-05-13 5 2020-06-16 2020-05-18 29 0 NaN
8 48002 2020-06-20 3 2020-06-23 2020-06-23 0 38 NaN
9 48002 2020-06-28 6 2020-07-05 2020-07-04 1 8 0.0
您可以使用数据填充NAN。fillna(0)
。请查看ID“48002”的第一个值是否为NaN,因为之前的值不在30天范围内。您可以使用滚动
方法仅对一些过去的元素进行操作。但是,日期应该是单调的(升序或降序),这意味着应该对日期进行排序
您可以尝试以下操作:
df['Invoice_Date'] = pd.to_datetime(df['Invoice_Date'])
df.set_index('Invoice_Date', inplace=True)
df.sort_index(inplace=True)
df['max'] = df.groupby('ID')['Delay'].transform(lambda x: x.rolling('30D', closed='left').max())
编辑:根据@Cainã的建议,包含了一个groupby
,以保证对每个唯一的ID
需要使用closed
参数指定不应包括当天
新数据框如下所示(此处仅按Invoice\u Date
排序)
如果我们也按ID
对其进行排序(通过运行df.reset_index().sort_值(['ID','Invoice_Date'))
),我们会得到:
您可以使用rolling
方法仅对一些过去的元素进行操作。但是,日期应该是单调的(升序或降序),这意味着应该对日期进行排序
您可以尝试以下操作:
df['Invoice_Date'] = pd.to_datetime(df['Invoice_Date'])
df.set_index('Invoice_Date', inplace=True)
df.sort_index(inplace=True)
df['max'] = df.groupby('ID')['Delay'].transform(lambda x: x.rolling('30D', closed='left').max())
编辑:根据@Cainã的建议,包含了一个groupby
,以保证对每个唯一的ID
需要使用closed
参数指定不应包括当天
新数据框如下所示(此处仅按Invoice\u Date
排序)
如果我们也按ID
对其进行排序(通过运行df.reset_index().sort_值(['ID','Invoice_Date'))
),我们会得到:
df.滚动
可以完成工作,而且可能是最有效的
df["Invoice_Date"] = df.Invoice_Date.astype("datetime64")
df["Max"] = df.groupby("ID").rolling("30d", on="Invoice_Date", closed="left").Delay.max().values
结果:
ID Invoice_Date Payment_Term Payment_Date Due_Date Delay Difference_Date Max
0 27459 2020-06-26 7 2020-07-05 2020-07-03 2 0 NaN
1 27459 2020-06-29 8 2020-07-05 2020-07-07 -2 3 2.0
2 27459 2020-06-30 3 2020-07-03 2020-07-03 0 1 2.0
3 27459 2020-07-14 6 2020-07-21 2020-07-20 1 14 2.0
4 27459 2020-07-25 4 2020-07-31 2020-07-29 2 11 2.0
5 27459 2020-07-30 7 2020-08-15 2020-08-06 9 5 2.0
6 27459 2020-08-02 8 2020-08-22 2020-08-10 12 3 9.0
7 48002 2020-05-13 5 2020-06-16 2020-05-18 29 0 NaN
8 48002 2020-06-20 3 2020-06-23 2020-06-23 0 38 NaN
9 48002 2020-06-28 6 2020-07-05 2020-07-04 1 8 0.0
df.滚动
可以完成工作,而且可能是最有效的
df["Invoice_Date"] = df.Invoice_Date.astype("datetime64")
df["Max"] = df.groupby("ID").rolling("30d", on="Invoice_Date", closed="left").Delay.max().values
结果:
ID Invoice_Date Payment_Term Payment_Date Due_Date Delay Difference_Date Max
0 27459 2020-06-26 7 2020-07-05 2020-07-03 2 0 NaN
1 27459 2020-06-29 8 2020-07-05 2020-07-07 -2 3 2.0
2 27459 2020-06-30 3 2020-07-03 2020-07-03 0 1 2.0
3 27459 2020-07-14 6 2020-07-21 2020-07-20 1 14 2.0
4 27459 2020-07-25 4 2020-07-31 2020-07-29 2 11 2.0
5 27459 2020-07-30 7 2020-08-15 2020-08-06 9 5 2.0
6 27459 2020-08-02 8 2020-08-22 2020-08-10 12 3 9.0
7 48002 2020-05-13 5 2020-06-16 2020-05-18 29 0 NaN
8 48002 2020-06-20 3 2020-06-23 2020-06-23 0 38 NaN
9 48002 2020-06-28 6 2020-07-05 2020-07-04 1 8 0.0
这不是按发票日期订购发票日期是根据IDi订购的请参见。是否也要按id对其进行分组?是的,需要按IDi对其进行分组。看起来Max
的最后一个元素有误:29不在30天窗口内。这不是按发票日期排序。发票日期是根据IDi排序的。请参阅。你也要按id分组吗?是的,它需要按id分组。看起来Max
的最后一个元素是错误的:29不在30天窗口内。我认为这不符合要求-他想要30天,不包括当前行。对不起,你是对的,我错过了。我已经改正了,雷卢布鲁斯托!它避免了不必要的循环
+1。尽管它仍然不符合OP的要求。考虑编辑你的答案,包括一个<代码> GlpBy< /Cl>语句。例如,“代码”> DF['Max '] = DF.GROMPBY(“ID”)[ [延迟] ]。转换(lambda x:x.滚动(‘30d’,‘关闭’=左’))/<代码>加上代码> df.ReStIdIdx()。但在这里它的方式更快!伟大的建议@CainãMaxCouto Silva!我很难包含一个groupby('ID')
,但这确实有效!我认为这不符合要求-他想要30天,不包括目前的赛道对不起,你是对的,我错过了。我已经改正了,雷卢布鲁斯托!它避免了不必要的循环
+1。尽管它仍然不符合OP的要求。考虑编辑你的答案,包括一个<代码> GlpBy< /Cl>语句。例如,“代码”> DF['Max '] = DF.GROMPBY(“ID”)[ [延迟] ]。转换(lambda x:x.滚动(‘30d’,‘关闭’=左’))/<代码>加上代码> df.ReStIdIdx()。但在这里它的方式更快!伟大的建议@CainãMaxCouto Silva!我很难包含一个groupby('ID')
,但这确实有效!用两行话来概括一切是相当优雅的。但这给我带来了一个错误(与相同)。你用的是什么版本的熊猫?pd.\uuuuuu版本\uuuuuuuuu->1.1.4tanks@Ralubrusto:)我其实觉得它有点不可读。不过可能表现得很好!我使用的是1.0.5
。升级到最新版本使其工作完美。干得好!:)回答得很好。我仍然不确定在使用groupby
时.rolling()
是如何工作的(关于数据顺序),但我添加了一个额外的行,其中27459作为ID,这似乎把结果搞砸了。因此,我建议在应用前对组日期进行排序(例如,df=df.sort_值(['ID','Invoice_Date'])
)。无论如何,干得好!用两行话来概括一切是相当优雅的。但这给我带来了一个错误(与相同)。你用的是什么版本的熊猫?pd.\uuuuuu版本\uuuuuuuuu->1.1.4tanks@Ralubrusto:)我其实觉得它有点不可读。不过可能表现得很好!我使用的是1.0.5
。升级到最新版本使其工作完美。干得好!:)回答得很好。我仍然不确定在使用groupby
时.rolling()
是如何工作的(关于数据顺序),但我添加了一个额外的行,其中27459作为ID,这似乎把结果搞砸了。所以我会