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

如何向量化Pandas中连续正值配对时间差计算代码?

向量化实现Pandas连续正值配对时间差计算

需求规则

  • 仅计算连续正值组成的配对的时间差,未配对的后续正值不计算
  • 连续正值之间允许存在任意数量的0
  • 遇到负值时立即重置配对追踪状态

原遍历实现代码

import pandas as pd
from datetime import datetime

# Sample data
data = {    
    'datetime': [
        datetime(2023, 11, 11, 8, 0, 0),
        datetime(2023, 11, 11, 8, 5, 0),
        datetime(2023, 11, 11, 8, 10, 0),
        datetime(2023, 11, 11, 8, 15, 0),
        datetime(2023, 11, 11, 8, 20, 0),
        datetime(2023, 11, 11, 8, 25, 0),
        datetime(2023, 11, 11, 8, 30, 0),
        datetime(2023, 11, 11, 8, 35, 0),
        datetime(2023, 11, 11, 8, 40, 0),
        datetime(2023, 11, 11, 8, 45, 0),
        datetime(2023, 11, 11, 8, 50, 0),
    ],
    'value': [1,  3, 4, 2, -1, 1, 0, 2, -3, 0, -3],                   
}

# Create the DataFrame
df = pd.DataFrame(data)

df['value_timespan'] = -1
# Initialize variables to keep track of the last positive value and its timestamp
last_positive_value = None
last_positive_timestamp = None
# Iterate through the DataFrame
for index, row in df.iterrows():
    if row['value'] > 0:
        if last_positive_value is not None:
            # Calculate the time span between the current positive value and the last positive value
            time_difference = (row['datetime'] - last_positive_timestamp).total_seconds()
            df.at[index, 'value_timespan'] = time_difference
            last_positive_value = None
            last_positive_timestamp = None
        else:
            last_positive_value = row['value']
            last_positive_timestamp = row['datetime']
    if row['value'] < 0:
        last_positive_value = None
        last_positive_timestamp = None        
print(df)

示例输出(原逻辑)

当value为[1, 3, 4, 2, -1, 1, 0, 2, -3, 0, -3]时,输出:

datetime  value  value_timespan
0 2023-11-11 08:00:00      1              -1
1 2023-11-11 08:05:00      3             300
2 2023-11-11 08:10:00      4              -1
3 2023-11-11 08:15:00      2             300
4 2023-11-11 08:20:00     -1              -1
5 2023-11-11 08:25:00      1              -1
6 2023-11-11 08:30:00      0              -1
7 2023-11-11 08:35:00      2             600
8 2023-11-11 08:40:00     -3              -1
9 2023-11-11 08:45:00      0              -1
10 2023-11-11 08:50:00     -3              -1

更新示例:当value为[1, 3, 1, -2, -1, 1, 0, 0, 3, 0, -3]时,输出:

datetime  value  timespan
0 2023-11-11 08:00:00      1     -1.0
1 2023-11-11 08:05:00      3    300.0
2 2023-11-11 08:10:00      1     -1.0
3 2023-11-11 08:15:00     -2     -1.0
4 2023-11-11 08:20:00     -1     -1.0
5 2023-11-11 08:25:00      1     -1.0
6 2023-11-11 08:30:00      0     -1.0
7 2023-11-11 08:35:00      0     -1.0
8 2023-11-11 08:40:00      3    900.0
9 2023-11-11 08:45:00      0     -1.0
10 2023-11-11 08:50:00     -3     -1.0

向量化实现方案

向量化实现的核心是通过标记分组、筛选有效配对,避免逐行遍历:

import pandas as pd
from datetime import datetime

# 示例数据(可替换为目标数据)
data = {    
    'datetime': [
        datetime(2023, 11, 11, 8, 0, 0),
        datetime(2023, 11, 11, 8, 5, 0),
        datetime(2023, 11, 11, 8, 10, 0),
        datetime(2023, 11, 11, 8, 15, 0),
        datetime(2023, 11, 11, 8, 20, 0),
        datetime(2023, 11, 11, 8, 25, 0),
        datetime(2023, 11, 11, 8, 30, 0),
        datetime(2023, 11, 11, 8, 35, 0),
        datetime(2023, 11, 11, 8, 40, 0),
        datetime(2023, 11, 11, 8, 45, 0),
        datetime(2023, 11, 11, 8, 50, 0),
    ],
    'value': [1,  3, 4, 2, -1, 1, 0, 2, -3, 0, -3],                   
}

df = pd.DataFrame(data)
df['value_timespan'] = -1

# 1. 标记关键状态:正值、负值
df['is_positive'] = df['value'] > 0
df['is_negative'] = df['value'] < 0

# 2. 创建分组:遇到负值则重置分组(用于隔离不同的配对区间)
df['group'] = df['is_negative'].cumsum()

# 3. 在每个分组内,标记有效正值的配对序号:每两个正值为一组(忽略0)
pos_mask = df['is_positive']
# 对每个分组内的正值进行计数,然后取模2得到配对序号
df['pair_id'] = df.groupby('group')['is_positive'].cumsum().where(pos_mask, -1) % 2

# 4. 提取配对的起始时间:每个分组内,pair_id=0的时间作为配对开始时间
df['start_time'] = df.groupby(['group', 'pair_id'])['datetime'].transform('first').where(df['pair_id'] == 1, pd.NaT)

# 5. 计算时间差,仅保留有效配对的结果
df['value_timespan'] = df.apply(
    lambda row: (row['datetime'] - row['start_time']).total_seconds() if pd.notna(row['start_time']) else -1,
    axis=1
)

# 清理临时列(可选)
df.drop(['is_positive', 'is_negative', 'group', 'pair_id', 'start_time'], axis=1, inplace=True)

print(df)

代码解释

  1. 状态标记:用is_positive和is_negative标记每行的数值状态,方便后续筛选和分组。
  2. 分组隔离:通过is_negative的累计求和创建分组,确保负值出现后,后续的配对不会和之前的正值关联。
  3. 配对序号分配:在每个分组内,对正值行进行连续计数,再取模2得到0/1的配对序号,0代表配对起始,1代表配对结束。
  4. 起始时间广播:将每个配对起始行(pair_id=0)的时间,传递到对应的结束行(pair_id=1)。
  5. 时间差计算:仅对配对结束行计算时间差,其他行保持-1。

该方案完全通过Pandas的向量化API实现,避免了iterrows()的低效遍历,性能更优,尤其适合大数据量场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 20:35:56