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

如何用Pandas基于其他列组合捕获指定列的值变化?

问题描述

假设存在如下DataFrame(df):

id  | date                  | type 
1   | 2023-03-01T10:00:00Z  |  A
1   | 2023-03-01T12:00:00Z  |  A
1   | 2023-03-05T09:09:00Z  |  D
1   | 2023-03-02T12:00:00Z  |  B
1   | 2023-03-02T19:00:00Z  |  C
1   | 2023-03-03T22:00:00Z  |  B
1   | 2023-03-04T12:00:00Z  |  C
1   | 2023-03-05T08:00:00Z  |  C
1   | 2023-03-04T17:00:00Z  |  C
2   | 2023-02-01T12:00:00Z  |  A
2   | 2023-02-03T10:00:01Z  |  A
2   | 2023-02-03T11:00:00Z  |  A
2   | 2023-02-02T13:13:13Z  |  A

按date排序后的结果(供参考):

id  | date                  | type 
1   | 2023-03-01T10:00:00Z  |  A
1   | 2023-03-01T12:00:00Z  |  A
1   | 2023-03-02T12:00:00Z  |  B
1   | 2023-03-02T19:00:00Z  |  C
1   | 2023-03-03T22:00:00Z  |  B
1   | 2023-03-04T12:00:00Z  |  C
1   | 2023-03-04T17:00:00Z  |  C
1   | 2023-03-05T08:00:00Z  |  C
1   | 2023-03-05T09:09:00Z  |  D
2   | 2023-02-01T12:00:00Z  |  A
2   | 2023-02-02T11:00:00Z  |  A
2   | 2023-02-02T13:13:13Z  |  A
2   | 2023-02-03T12:00:00Z  |  A

注意:对于(id, date)的组合,不会出现重复的type值

最终目标DataFrame如下:

id  | old_type | new_type | change_date
1   |     A    |    B     | 2023-03-02T12:00:00Z
1   |     B    |    C     | 2023-03-02T19:00:00Z
1   |     C    |    B     | 2023-03-03T22:00:00Z
1   |     B    |    C     | 2023-03-04T12:00:00Z
1   |     C    |    D     | 2023-03-05T09:09:00Z

由于id为2的记录在不同日期间type无变化,因此不会出现在结果中。需要通过Pandas实现上述转换。

解决方案

可以通过以下步骤实现需求:

  1. 按id和date排序,确保数据按用户和时间顺序排列
  2. 去除同一id下连续重复的type记录,保留每个type变化的起始记录
  3. 通过移位操作生成新旧type的对应关系
  4. 过滤无变化的记录,整理结果列名

具体代码如下:

import pandas as pd

# 1. 按id和date排序
df_sorted = df.sort_values(['id', 'date'], ignore_index=True)

# 2. 移除同一id下连续重复的type记录
df_dedup = df_sorted[df_sorted['type'] != df_sorted.groupby('id')['type'].shift()]

# 3. 生成old_type、new_type和change_date字段
df_result = df_dedup.assign(
    old_type=df_dedup.groupby('id')['type'].shift(),
    new_type=df_dedup['type'],
    change_date=df_dedup['date']
)

# 4. 过滤无前置type的记录,并整理列顺序
df_result = df_result.dropna(subset=['old_type'])[['id', 'old_type', 'new_type', 'change_date']]

# 重置索引(可选)
df_result = df_result.reset_index(drop=True)

代码说明:

  • 排序:sort_values(['id', 'date'])保证同一用户的记录按时间先后排列,确保后续移位操作的正确性。
  • 去重连续重复type:通过groupby('id')['type'].shift()获取同一用户的上一条type,对比当前type,仅保留不同的行,去掉同一type的连续重复记录(比如id=1的两条A记录只保留第一条)。
  • 生成新旧type:再次对每个用户的type移位,移位结果即为当前type的上一个类型(old_type),当前type为new_type,当前date就是变化发生的时间。
  • 过滤无效行:每个用户的第一条记录没有上一个type,用dropna去掉,剩下的就是所有type变化的记录。

执行后即可得到目标DataFrame。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:53:17