You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas DataFrame中按月基于B/M指标生成指定规则的新列?

Pandas 分组打标实现方案

核心思路为按日期分组后对B/M指标做二分位切割,无需拆分出多个单月DataFrame,即可完成Signal列批量赋值。

方法1:qcut 快速实现(推荐标准场景使用)

import pandas as pd

# 按日期(索引)分组,将每组B/M等分为2组,直接对应标签-1和1
df['Signal'] = df.groupby(level='Date')['B/M'].transform(
    lambda x: pd.qcut(x, q=2, labels=[-1, 1])
)
# 按需转换为整数类型
df['Signal'] = df['Signal'].astype(int)

逻辑说明:

  • groupby(level='Date'):按索引列Date分组,单月所有股票为一组;如果你的Date后续调整为普通列,替换为groupby('Date')即可
  • pd.qcut(x, q=2):将每组B/M值按数量等分为2份,前50%(低B/M)对应标签-1,后50%(高B/M)对应标签1,和你给出的预期输出完全匹配
  • 如果单月样本量为奇数,qcut默认将多出来的1条样本分到高B/M组,符合常规金融因子分组的惯例。如果需要处理重复的B/M值,可以增加duplicates='drop'参数适配。

方法2:rank 自定义实现(适合需要调整重复值规则的场景)

如果需要自定义相同B/M值的分组逻辑,可以用排名+阈值判断的方式实现:

# 分组计算单月B/M排名、单月样本总量
df['bm_rank'] = df.groupby(level='Date')['B/M'].rank(method='first')
df['month_sample_cnt'] = df.groupby(level='Date')['B/M'].transform('count')

# 按排名是否超过中位数判断Signal值
df['Signal'] = df.apply(lambda x: 1 if x['bm_rank'] > x['month_sample_cnt']/2 else -1, axis=1)

# 删除辅助列
df = df.drop(columns=['bm_rank', 'month_sample_cnt'])

可以通过调整rank的method参数修改重复值的排名规则:可选值包括average/min/max/first/dense,适配不同的业务需求。


内容的提问来源于stack exchange,提问作者Gonçalo Franchini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 19:39:03