如何在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
相关产品推荐
相关产品推荐

