Python 如何将不同长度的时间窗口应用于数据帧
我有以下数据框,每行代表一笔销售交易:Python 如何将不同长度的时间窗口应用于数据帧,python,pandas,numpy,dataframe,Python,Pandas,Numpy,Dataframe,我有以下数据框,每行代表一笔销售交易: startDate INDEX_250 priceDeal 2013-05-02 00:00:00 9312.000 255000.000 2013-09-17 00:00:00 11121.000 368209.000 2013-10-09 00:00:00 11121.000 254000.000 2013-11-14 00:00:00 11121.000 520000.000 2013-11-22 00:00
startDate INDEX_250 priceDeal
2013-05-02 00:00:00 9312.000 255000.000
2013-09-17 00:00:00 11121.000 368209.000
2013-10-09 00:00:00 11121.000 254000.000
2013-11-14 00:00:00 11121.000 520000.000
2013-11-22 00:00:00 11121.000 201000.000
2014-02-05 00:00:00 11121.000 260000.000
2014-02-28 00:00:00 11121.000 425000.000
2014-03-01 00:00:00 11121.000 315000.000
2014-03-11 00:00:00 9312.000 427000.000
2014-04-27 00:00:00 9312.000 138070.000
2014-06-20 00:00:00 9312.000 270000.000
2014-07-21 00:00:00 9312.000 282000.000
2014-07-31 00:00:00 9312.000 308806.350
2014-09-27 00:00:00 11121.000 170000.000
2014-10-05 00:00:00 11121.000 171658.220
2014-10-11 00:00:00 11121.000 292000.000
2014-10-13 00:00:00 11121.000 125000.000
2014-10-30 00:00:00 9312.000 95000.000
2014-11-18 00:00:00 9312.000 158942.280
2015-01-25 22:00:00 11121.000 238829.370
2015-03-11 00:00:00 11121.000 180695.960
2015-03-14 00:00:00 9312.000 320932.860
2015-03-21 00:00:00 11121.000 139872.000
2015-09-04 00:00:00 11121.000 140000.000
2015-09-09 00:00:00 9312.000 235000.000
我想看看从第一笔销售交易到2013-09-17的前30天和60天,每个(按索引250分组)发生了多少笔销售交易。示例数据集仅用于一个索引_250
,但也有其他索引编号,以下输出是可取的:
startDate INDEX_250 nrTargets_gr_250_30 nrTargets_gr_250_60
2013-10-17 11121 2.000 2.000
2013-11-16 11121 1.000 3.000
2013-12-16 11121 1.000 2.000
2014-01-15 11121 0.000 1.000
2014-02-14 11121 1.000 1.000
2014-03-16 11121 2.000 3.000
2014-04-15 11121 0.000 2.000
2014-10-12 11121 3.000 3.000
2014-11-11 11121 1.000 4.000
2014-12-11 11121 0.000 1.000
2015-02-09 11121 1.000 1.000
2015-03-11 11121 0.000 1.000
2015-04-10 11121 2.000 2.000
2015-05-10 11121 0.000 2.000
2015-09-07 11121 1.000 1.000
2015-10-07 11121 0.000 1.000
2016-02-04 11121 1.000 1.000
2016-03-05 11121 0.000 1.000
2017-01-29 11121 1.000 1.000
我注意到您希望将startDate更改为相应的
30天期限,从您的开始日期开始
另一个细节是,您希望结果按索引\u 250分组-
之前(两个时期内)有多少笔交易与
索引250的值相同
还请注意,可以在窗口上执行滚动计算
包含多个未来期间的行,而您需要
之前的30或60天内的交易数量,以及
滚动不允许周期数为负数
这就是为什么我采取了与“普通”滚动不同的方法
从辅助变量开始:
td30 = pd.Timedelta('30D')
dRng = pd.date_range(start='2013-09-17', end=df.startDate.max() + td30,
freq='30D', closed='left')
然后定义以下计算两个目标的函数:
def targets(grp):
grp['Prd'] = grp.startDate.apply(lambda x: dRng.asof(x) + td30)
grp.set_index('Prd', inplace=True)
trg30 = grp.groupby(level=0).INDEX_250.count()\
.rename('nrTargets_gr_250_30').reindex(dRng, fill_value=0)
trg60 = trg30.rolling(2).sum().rename('nrTargets_gr_250_60')\
.fillna(0, downcast='infer')
trg30 = trg30[trg30 > 0]
trg60 = trg60[trg60 > 0]
return trg30.to_frame().join(trg60, how='outer')\
.fillna(0, downcast='infer').rename_axis('startDate')
应用它并重置索引(仅按此顺序,以获得正确的列顺序):
注:
- 我只在您选择的开始日期当天或之后选择startDate的行 规定(2013-09-17)
- 两个目标列的类型都是int。我认为它更自然, 因为这些列包含交易的数量,本质上 只是一个整数
def trgReformat(trg):
trg = trg[trg.nrTargets_gr_250 > 0].copy()
trg['avgPrice'] = trg.sm / trg.nrTargets_gr_250
return trg.drop(columns='sm')
其次,将目标函数定义为:
def targets(grp):
grp['Prd'] = grp.startDate.apply(lambda x: dRng.asof(x) + td30)
grp.set_index('Prd', inplace=True)
trg30 = grp.groupby(level=0).agg(
nrTargets_gr_250=('INDEX_250', 'count'), sm=('priceDeal', 'sum'))\
.reindex(dRng, fill_value=0)
trg60 = trg30.rolling(2).sum().fillna(0, downcast='infer')
trg30 = trgReformat(trg30)
trg60 = trgReformat(trg60)
return trg30.join(trg60, how='outer', lsuffix='_30', rsuffix='_60')\
.fillna(0, downcast='infer').rename_axis('startDate')
此函数使用命名聚合来计算:
- NRU gr_250-行数
- sm-价格之和
此函数的应用与以前一样。您能提供两个索引的数据吗?@QuangHoang我做了一个编辑。非常感谢,它可以工作,我如何更改它,使每个时间窗口都能计算过去30天和60天的平均
priceDeal
?
def trgReformat(trg):
trg = trg[trg.nrTargets_gr_250 > 0].copy()
trg['avgPrice'] = trg.sm / trg.nrTargets_gr_250
return trg.drop(columns='sm')
def targets(grp):
grp['Prd'] = grp.startDate.apply(lambda x: dRng.asof(x) + td30)
grp.set_index('Prd', inplace=True)
trg30 = grp.groupby(level=0).agg(
nrTargets_gr_250=('INDEX_250', 'count'), sm=('priceDeal', 'sum'))\
.reindex(dRng, fill_value=0)
trg60 = trg30.rolling(2).sum().fillna(0, downcast='infer')
trg30 = trgReformat(trg30)
trg60 = trgReformat(trg60)
return trg30.join(trg60, how='outer', lsuffix='_30', rsuffix='_60')\
.fillna(0, downcast='infer').rename_axis('startDate')