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

如何在Pandas中按ID分组获取值变更后的下一个name值?

问题描述

现有如下数据集:

id  name date_and_hour
1   SS   1/1/2019 00:12
1   SS   1/1/2019 00:13
1   SS   1/1/2019 00:14
1   SB   1/1/2019 00:15
1   SS   1/1/2019 00:16
2   SE   1/1/2019 01:15
2   SR   1/1/2019 01:16
2   SS   1/1/2019 01:17
2   SR   1/1/2019 01:18

需要按id分组,为每行添加next_name列,填充下一个发生值变更的name值,预期输出如下:

id  name date_and_hour   next_name
1   SS   1/1/2019 00:12  SB
1   SS   1/1/2019 00:13  SB
1   SS   1/1/2019 00:14  SB
1   SB   1/1/2019 00:15  SS
1   SS   1/1/2019 00:16  null
2   SE   1/1/2019 01:15  SR
2   SR   1/1/2019 01:16  SS
2   SS   1/1/2019 01:17  SR
2   SR   1/1/2019 01:18  null
解决方案

方法一:Python Pandas 实现

核心逻辑:按id分组标记name的变化点,提取后续第一个变化的name值,再向前填充到当前变化段的所有行。

代码示例:

import pandas as pd

# 构造原始数据(实际场景可替换为pd.read_csv等读取方式)
df = pd.DataFrame({
    'id': [1,1,1,1,1,2,2,2,2],
    'name': ['SS','SS','SS','SB','SS','SE','SR','SS','SR'],
    'date_and_hour': ['1/1/2019 00:12','1/1/2019 00:13','1/1/2019 00:14','1/1/2019 00:15','1/1/2019 00:16','1/1/2019 01:15','1/1/2019 01:16','1/1/2019 01:17','1/1/2019 01:18']
})

# 标记当前行name与上一行不同的变化点
df['name_changed'] = df.groupby('id')['name'].shift() != df['name']
# 提取变化点的name值,并向下偏移一位得到下一个变化的name
df['next_name_temp'] = df.loc[df['name_changed'], 'name'].groupby(df['id']).shift(-1)
# 按id分组向前填充,让同一段的所有行共享下一个变化的name
df['next_name'] = df.groupby('id')['next_name_temp'].ffill()
# 清理临时列
df = df.drop(['name_changed', 'next_name_temp'], axis=1)

print(df)

执行后最后一行的next_name为NaN,对应预期的null。

方法二:SQL 实现(以MySQL为例)

通过窗口函数给每行编号,再关联查询当前行之后第一个name不同的记录,获取其name值。

代码示例:

WITH ranked_data AS (
    SELECT 
        id,
        name,
        date_and_hour,
        ROW_NUMBER() OVER (PARTITION BY id ORDER BY date_and_hour) AS rn
    FROM your_table_name -- 替换为你的实际表名
)
SELECT 
    rd1.id,
    rd1.name,
    rd1.date_and_hour,
    rd2.name AS next_name
FROM ranked_data rd1
LEFT JOIN ranked_data rd2 
    ON rd1.id = rd2.id 
    AND rd2.rn = (
        SELECT MIN(rn) 
        FROM ranked_data rd3 
        WHERE rd3.id = rd1.id 
          AND rd3.rn > rd1.rn 
          AND rd3.name != rd1.name
    )
ORDER BY rd1.id, rd1.rn;

查询结果中无后续变化的行next_name会显示NULL,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:35:50