pandas高级技巧之多级索引和分组操作

在量化领域,Pandas是不可或缺的工具,它以强大的数据处理和分析功能,极大地简化了数据操作流程。

今天我们介绍两个技巧,都跟因子检验场景相关。第一个技巧是日期按月对齐;第二个是如何提取分组的前n条记录。讲解的概念涉及到group操作、索引的frequency概念以及多级索引的操作(读取和删除)。

在最后一个例子中,更是反复使用了groupby,以简洁的语法,完成了一个略为复杂的数据操作。

日期按月对齐

我们在做因子检验的时候,如果使用的是日线以上的频率,依赖于所使用的数据源,就有可能遇到这样一种情况:比如,今年的1月份收盘日是1月31日,但个股可能在1月31日停牌,那么数据源传给我们的月线,就可能把日期标注在1月30日。也就是,我们在生成月度因子数据时,有的个股的日期是1月31日,有的则是1月30或者更早的时间。

如果我们使用Alphalens来进行因子检验,就会产生日期无法对齐,计算前向收益出错的问题。不过,这不是我们今天要介绍的问题。我们今天只讲解决方案,即如何实现所有个股的因子日期都对齐到月。

假设我们有以下数据:

在这里插入图片描述

这里无论是1月还是2月,两个个股的收盘日期都不一致。最简单的方案是使用index.to_period函数,将日期对齐到月份。

df.index = df.index.to_period(freq='M')

经过转换,就会生成下面的结果:

这样的转换尽管实现了对齐,但会丢失具体的日期信息。我们也可以使用groupby来实现同样的功能:

(df
    .groupby(['asset', pd.Grouper(freq='M')])
    .last()
    .reset_index("asset")

结果是:

语法要点是,asset与index构成一个事实上的惟一索引,我们现在要调整索引的日期,按’asset’进行分组,并且通过Grouper来指定分组的频率。Grouper是作用在索引上的。

.last()提供了如何从分组记录中选取记录的功能。它是一种聚合函数,除此之外,还有first, min, max, mean等。在我们的例子中,由于asset与index构成一个惟一的索引,所以,无论使用first, last还是min, max,结果都一样。

提取分组的前n条记录

假如,我们通过因子检验,已经确认了某个因子有效,想使用test数据集来进行验证。test数据集也由好多期数据组成,我们需要对每一期数据,取前20%的股票,然后计算它在之后的T1~Tn期的收益,以决定这个因子是否能投入使用。

这实际上是一个DataFrame分组,再取头部n条记录的问题。


假设数据是:

df = pd.DataFrame(
    [
        (datetime.datetime(2024, 1, 31), "000001", 9.86),
        (datetime.datetime(2024, 1, 31), "000002", 10.2),
        (datetime.datetime(2024, 1, 31), "000003", 9.84),
        (datetime.datetime(2024, 1, 31), "000004", 11.2),
        (datetime.datetime(2024, 2, 29), "000001", 10.2),
        (datetime.datetime(2024, 2, 29), "000002", 11.2),
        (datetime.datetime(2024, 2, 29), "000003", 9.83),
        (datetime.datetime(2024, 2, 29), "000004", 11),
    ],
    columns=["date", "asset", "factor"]
)

我们要取每个月factor最大的前n个,并且生成一个dict,key为每月日期,values为对应的asset数组。

top_n_assets = (df
      .groupby(level=0)
      .apply(lambda x: x.nlargest(2, 'factor')['asset'])
      .reset_index(level = 1, drop = True)
      .groupby(level=0)
      .apply(list)
     ).todict()

top_n_assets

输出结果是:

date
2024-01-31    [000004, 000002]
2024-02-29    [000002, 000004]
Name: asset, dtype: object

这里的技巧是,当我们要按索引进行分组时,我们要使用grouby(level=?)的语法。Pandas支持多级索引,第一级索引一般使用level=0来引用,第二级索引使用level=1来引用。

在使用groupby之后,生成的DataFrame就有了两级索引,这个中间结果显示如下:

date        date      
2024-01-31  2024-01-31    000004
            2024-01-31    000002
2024-02-29  2024-02-29    000002
            2024-02-29    000004
Name: asset, dtype: object

我们通过第4行的reset_index来删除掉第二级索引。注意在Pandas中,删除索引也是通过调用reset_index来实现的。到此为止,我们实际上已经实现了提取分组的前n条记录的任务。

第5~6行是将提取结果扁平化,即将按多行排列的asset,压缩成一个list,结果仍然是一个DataFrame,但每个日期只有一行,其值包含了当期前n个asset。

今天介绍的两个小技巧,都是因子检验中常常遇到的。熟悉掌握Pandas技巧,就能快速搞定因子检验,加快我们因子研发的迭代速度,你学会了吗?

  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

量化风云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值