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

如何用pandas/numpy检测DataFrame相邻时间步的列值符号变化

Pandas/Numpy 相邻时间步同ID符号变化统计方案

你之前使用的「筛选负值+去重」逻辑存在本质缺陷:该方法只能统计所有出现过负值的ID,完全没有做相邻时间步的同ID值比对,既会把很早之前就变负、后续一直为负的ID错误统计,也会漏掉负转正的变化场景,效率和准确率都无法满足要求。

实现思路

全程使用向量化操作,避免逐行循环,适配最大时间步到10000000的大数据量场景:

  • 先按id和TIMESTEP排序,保证每个ID的时间序列顺序正确
  • 按id分组取上一个相邻时间步的y值,和当前步y值做符号比对
  • 标记出所有前后值异号的记录(即发生符号变化的记录)
  • 按TIMESTEP维度聚合,统计发生变化的ID数量、对应mass值的和
  • 可选补全从起始到10000000的所有时间步,无变化的时间步填充0值

完整实现代码

import pandas as pd
import numpy as np

# 1. 排序保证时序正确
df = df.sort_values(by=['id', 'TIMESTEP'], ignore_index=True)

# 2. 取每个ID上一个相邻时间步的y值
df['prev_y'] = df.groupby('id')['y'].shift(1)

# 3. 标记符号变化:前后值符号乘积<0即为异号,自动排除第一个时间步(无前值不参与统计)
df['is_sign_change'] = np.sign(df['y']) * np.sign(df['prev_y']) < 0

# 4. 按时间步聚合统计
result = df[df['is_sign_change']].groupby('TIMESTEP').agg(
    id_count=('id', 'nunique'),
    mass=('mass', 'sum')
).reset_index()

# 5. (可选)补全到10000000的所有时间步,无变化的步填充0
full_timesteps = pd.DataFrame({'TIMESTEP': range(int(df['TIMESTEP'].min()) + 1, 10000001)})
result = full_timesteps.merge(result, on='TIMESTEP', how='left').fillna({'id_count': 0, 'mass': 0})
result['id_count'] = result['id_count'].astype(int)

逻辑说明

  • 符号判断使用np.sign实现,自动识别正转负、负转正两种变化场景,不会漏判
  • 全流程为pandas/numpy原生向量化计算,千万级数据量运行效率远高于逐行遍历或筛选去重方案
  • 针对给出的样例数据:TIMESTEP=2900时,id=313的上步y值为正、当前y值为负,会被正确标记为变化,聚合结果为id_count=1、mass=0.795699,和预期完全一致
  • 如果业务中需要特殊处理y=0的边界场景(比如把0归为正/负类),可以在标记符号变化前先对y值做替换即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:15:31