我有以下数据框,每行代表一次销售交易:
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
我想查看在前30天nrTargets_gr_250_30
和60天nrTargets_gr_250_60
中,第一笔销售交易INDEX_250
中的每笔交易(按2013-09-17
}发生了多少笔交易。示例数据集仅适用于一个INDEX_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
答案 0 :(得分:1)
我注意到您希望将 startDate 更改为各自的末尾 从开始日期算起30天。
另一个细节是您希望结果按 INDEX_250 分组- 之前(在两个时期内)有多少笔交易 INDEX_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')
应用它并重置索引(按此顺序,以对列进行正确排序):
df2 = df[df.startDate >= '2013-09-17'].groupby('INDEX_250')\
.apply(targets).reset_index(level=[0]).reset_index()
注意:
最后一件事是将 INDEX_250 的类型更改为 int :
df2.INDEX_250 = df2.INDEX_250.astype(int)
INDEX_250 组的结果与您指定的相同,但不包括 2016 和 2017 中的结果行,这些行不包含在您的 样本数据。
以每个“最终”日期的平均价格扩展结果 和两个目标,都需要进行两次更改。
首先,定义另一个函数以“重新格式化” target DataFrame:
def trgReformat(trg):
trg = trg[trg.nrTargets_gr_250 > 0].copy()
trg['avgPrice'] = trg.sm / trg.nrTargets_gr_250
return trg.drop(columns='sm')
第二,将 targets 函数定义为:
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')
此函数使用命名聚合进行计算:
原因是 trg60 的计算是使用 rolling (对于 2个连续的30天时段),因此仅 average 是不够的 在这里。
可以在重新格式化时进行平均价格的计算 每个 target 的对象。
此功能的应用与以前一样。