如何使用Pandas根据其他列的组合捕获列值的变化?

c86crjj0  于 2023-03-06  发布在  其他
关注(0)|答案(1)|浏览(123)

假设我有这样一个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

按日期排序后(供参考),

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)组合不可能具有相同的“类型”

最终df应如下所示,

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的记录,因为不同日期之间类型没有变化。
对于我如何利用Pandas来操纵数据以实现这种转换,有什么建议吗?任何帮助都将不胜感激。先谢了。

c9qzyr3d

c9qzyr3d1#

您可以使用groupby.shift和一些过滤:

# ensure dates are sorted in a stable way
(df.sort_values(by='date', kind='stable')
   # get previous type per group
   .assign(old_type=lambda d: d.groupby('id')['type'].shift())
   # rename columns
   .rename(columns={'type': 'new_type', 'date': 'change_date'})
   # keep only rows in which the type changed
   .loc[lambda d: d['old_type'].ne(d['new_type']) & d['old_type'].notna()]
   # optional: reorder columns
   [['id', 'old_type', 'new_type', 'change_date']]
)

输出:

id old_type new_type           change_date
3   1        A        B  2023-03-02T12:00:00Z
4   1        B        C  2023-03-02T19:00:00Z
5   1        C        B  2023-03-03T22:00:00Z
6   1        B        C  2023-03-04T12:00:00Z
2   1        C        D  2023-03-05T09:09:00Z

相关问题