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

如何基于sec_ID检测code列首次变更?附DataFrame处理需求

解决按证券分组检测code首次变更的问题

你的核心问题是没有按sec_ID分组独立计算code的变化:原始代码里的data['code'].diff()是全局计算差异,会跨不同证券的行进行比对,导致错误识别跨组的"变更"。针对你400万行的大数据量,我提供两种高效的解决方案,都能保证每个证券的检测逻辑独立重置:

方案一:分组自定义逻辑(直观易读)

通过groupby.apply()对每个证券组单独处理逻辑,适合需要清晰理解每一步的场景:

import pandas as pd

# 确保数据已按sec_ID和date升序排序(你提到已完成此步骤)
def process_sec_group(group):
    # 获取当前证券的初始code值(首行的code)
    initial_code = group['code'].iloc[0]
    # 情况1:该证券所有code始终为初始值(0),返回首行
    if (group['code'] == initial_code).all():
        return group.iloc[[0]]
    # 情况2:存在code变更,返回第一个变更的行
    else:
        # 找到第一个不等于初始值的行的索引
        first_change_pos = group[group['code'] != initial_code].index[0]
        return group.loc[[first_change_pos]]

# 应用逻辑到每个分组,合并结果
final_result = data.groupby('sec_ID', group_keys=False).apply(process_sec_group).reset_index(drop=True)

方案二:矢量化分组diff(性能更优)

针对大数据量,优先用矢量化操作替代apply,速度更快:

# 1. 按sec_ID分组,计算组内code的差异(每个组独立计算diff,跨组不会干扰)
data['group_code_diff'] = data.groupby('sec_ID')['code'].diff()

# 2. 标记每个证券是否存在code变更
has_code_change = data.groupby('sec_ID')['group_code_diff'].any()

# 3. 提取两类目标行:
#    - 有变更的证券:取第一个diff非0的行
first_change_rows = data[
    data['group_code_diff'].notna() & (data['group_code_diff'] != 0)
].groupby('sec_ID').nth(0)

#    - 无变更的证券:取首行
no_change_rows = data[
    data['sec_ID'].isin(has_code_change[~has_code_change].index)
].groupby('sec_ID').nth(0)

# 4. 合并结果并整理格式
final_result = pd.concat([first_change_rows, no_change_rows]).reset_index()
final_result = final_result.sort_values('sec_ID').reset_index(drop=True)

结果验证

用你提供的示例数据测试,两种方案都会得到期望的输出:

datesec_IDcode
2015-12-18abc1
2016-01-16def0
2016-11-17xyz-1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:50:25