如何按ID分组计算DataFrame的OUTPUT列:输入列表变化次数统计
嘿,这个需求我刚好处理过类似的,用 Pandas 可以轻松实现,我给你一步步拆解怎么做:
解决方法:用 Pandas 分组处理自定义逻辑
首先,我们需要先把input列的字符串转换成列表,方便后续处理每个元素的变化。然后按ID分组,对每个组内的行分别计算OUTPUT值。
步骤1:构造示例DataFrame(如果你的数据已经存在,这步可以跳过)
import pandas as pd # 你的示例数据 data = { 'ID': [1, 1, 1, 2, 2, 3], 'input': ['A,B', 'B,C,D', 'C', 'E,f', 'A,B,C', 'E'] } df = pd.DataFrame(data)
步骤2:将input列转为元素列表
把逗号分隔的字符串拆成列表,方便后续操作:
df['input_list'] = df['input'].str.split(',')
步骤3:定义分组处理函数
我们写一个函数,专门处理每个ID组内的计算逻辑:
def compute_output(group): # 计算当前行input列表内部的相邻元素变化次数(元素不同才算一次) group['internal_changes'] = group['input_list'].apply( lambda lst: sum(a != b for a, b in zip(lst[:-1], lst[1:])) ) # 获取前一行input列表的最后一个元素(组内第一行没有前一行,所以是None) group['prev_last'] = group['input_list'].shift().apply( lambda x: x[-1] if x is not None else None ) # 获取当前行input列表的第一个元素 group['curr_first'] = group['input_list'].apply(lambda x: x[0]) # 计算跨行变化次数:前一行最后元素和当前行第一个元素不同则算1次,组内第一行设为0 group['cross_changes'] = (group['prev_last'] != group['curr_first']).astype(int) group['cross_changes'].iloc[0] = 0 # 组内第一行没有跨行变化 # 最终OUTPUT = 内部变化次数 + 跨行变化次数 group['OUTPUT'] = group['internal_changes'] + group['cross_changes'] return group
步骤4:分组应用函数并整理结果
按ID分组后应用上面的函数,然后去掉中间辅助列,保留需要的列:
# 分组处理 df = df.groupby('ID', group_keys=False).apply(compute_output) # 保留原始列和OUTPUT列 df = df[['ID', 'input', 'OUTPUT']]
运行完这些代码后,你得到的df就会和你给出的示例完全一致啦!
验证结果
最终的DataFrame会是这样:
| ID | input | OUTPUT |
|---|---|---|
| 1 | A,B | 1 |
| 1 | B,C,D | 2 |
| 1 | C | 1 |
| 2 | E,f | 1 |
| 2 | A,B,C | 3 |
| 3 | E | 0 |
完全符合你要求的规则~
内容的提问来源于stack exchange,提问作者SS25
相关产品推荐
相关产品推荐

