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

如何用Pandas计算指数成分不变的连续天数均值?

解决指数成分连续不变天数的平均值计算问题

我明白你的需求啦——要从这个日期索引的市值DataFrame里,找出成分(非零列集合)连续不变的时间段,统计每个时间段的天数,再求这些天数的平均值。下面给你一步步拆解实现方法,附带示例代码:

步骤1:构造示例数据(方便演示)

先模拟一个和你描述一致的DataFrame,这样你可以直接跑代码验证:

import pandas as pd

# 生成日期索引
dates = pd.date_range('2023-01-01', periods=10)
# 公司列名
companies = ['a', 'b', 'c', 'd']
# 市值数据:0代表未加入/已退出指数
data = [
    [100, 200, 0, 0],   # 成分:a、b
    [150, 250, 0, 0],   # 成分:a、b
    [0, 300, 150, 0],   # 成分:b、c
    [0, 350, 200, 0],   # 成分:b、c
    [0, 400, 250, 0],   # 成分:b、c
    [200, 0, 300, 100], # 成分:a、c、d
    [250, 0, 350, 150], # 成分:a、c、d
    [300, 100, 400, 200],# 成分:a、b、c、d
    [350, 150, 450, 250],# 成分:a、b、c、d
    [0, 200, 500, 300]   # 成分:b、c、d
]
df = pd.DataFrame(data, index=dates, columns=companies)

步骤2:给每行标记唯一的成分标识

我们需要给每行的非零列集合生成一个可哈希的唯一标识,这样才能判断两行的成分是否完全相同。这里有两种常用方式:

方式A:用frozenset(无序集合,适合不关心列顺序的场景)

# 对每行,提取非零列的名称,转成不可变的frozenset(可作为分组键)
component_sets = df.apply(lambda row: frozenset(row[row > 0].index), axis=1)

方式B:用排序后的字符串拼接(更直观,适合需要查看成分的场景)

# 对每行,提取非零列名称并排序,拼接成字符串
component_keys = df.apply(lambda row: ','.join(sorted(row[row > 0].index)), axis=1)

两种方式效果等价,选你习惯的就行。

步骤3:识别连续相同成分的分组

通过比较当前行和上一行的成分标识,生成分组ID——连续相同的成分会被分到同一个组:

# 以方式A为例,方式B只需把component_sets换成component_keys即可
group_ids = (component_sets != component_sets.shift()).cumsum()

解释:shift()把上一行的成分标识移到当前行位置,比较是否和当前行不同;cumsum()会在每次成分变化时累加1,这样连续相同的行就会拥有同一个group_id。

步骤4:计算连续天数的平均值

统计每个分组的行数(即连续天数),然后求这些天数的平均值:

# 统计每个分组的行数
continuous_days = group_ids.value_counts()
# 计算平均值
average_continuous_days = continuous_days.mean()

print(f"指数成分不变的连续天数平均值:{average_continuous_days:.2f}")

在示例数据中,输出结果是2.00,因为各分组的天数分别是2、3、2、2、1,平均值为(2+3+2+2+1)/5=2。

简化版链式代码

如果你不想保留中间变量,可以把步骤2-4合并成一行:

average_days = (df.apply(lambda row: frozenset(row[row > 0].index), axis=1)
               .pipe(lambda x: (x != x.shift()).cumsum())
               .value_counts()
               .mean())

边界情况说明

  • 如果所有日期的成分完全相同,那么平均值就是DataFrame的总行数;
  • 如果每行成分都不一样,平均值就是1;
  • 空DataFrame(无数据)的话需要额外处理,不过一般你的场景不会遇到这种情况。

内容的提问来源于stack exchange,提问作者bbarroso

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 06:42:43