如何用Pandas基于内部编号提取连续值并生成新列?
问题描述
我有如下Pandas DataFrame:
Answers all_answers Score 0 0.0 0 72 1 0.0 0 73 2 0.0 0 74 3 1.0 1 1 4 -1.0 1 2 5 1.0 1 3 6 -1.0 1 4 7 1.0 1 5 8 0.0 0 1 9 0.0 0 2 10 -1.0 1 1 11 0.0 0 1 12 0.0 0 2 13 1.0 1 1 14 0.0 0 1 15 0.0 0 2 16 1.0 1 1
各列含义:
Answers:计算流程中符号变化的信号;all_answers:去除Answers负号后的结果;Score:all_answers的连续计数,统计连续1或0的出现次数。
需求:新增第四列New,仅保留all_answers连续出现5次1时对应的Answers值,其余情况设为0,最终结果如下:
Answers all_answers Score New 0 0.0 0 72 0 1 0.0 0 73 0 2 0.0 0 74 0 3 1.0 1 1 1 4 -1.0 1 2 -1 5 1.0 1 3 1 6 -1.0 1 4 -1 7 1.0 1 5 1 8 0.0 0 1 0 9 0.0 0 2 0 10 -1.0 1 1 0 11 0.0 0 1 0 12 0.0 0 2 0 13 1.0 1 1 0 14 0.0 0 1 0 15 0.0 0 2 0 16 1.0 1 1 0 17 0.0 0 1 0
能否通过Pandas实现该需求?
实现方案
当然可以用Pandas实现,核心思路是先定位到all_answers连续5次为1的分组,再对该分组内的Answers值保留,其余行设为0。
具体步骤:
- 标记连续相同值的分组:通过对比当前行与上一行的
all_answers值,生成每个连续相同值的唯一分组ID; - 筛选目标分组:统计每个分组的长度,找出
all_answers=1且长度恰好为5的分组; - 生成New列:判断每行是否属于目标分组,是则保留
Answers值,否则赋值为0。
代码实现(直观版):
import pandas as pd # 构造示例数据 data = { 'Answers': [0.0, 0.0, 0.0, 1.0, -1.0, 1.0, -1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0], 'all_answers': [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], 'Score': [72, 73, 74, 1, 2, 3, 4, 5, 1, 2, 1, 1, 2, 1, 1, 2, 1] } df = pd.DataFrame(data) # 生成连续分组ID:当前行与上一行值不同时,分组ID+1 df['group_id'] = df['all_answers'].ne(df['all_answers'].shift()).cumsum() # 统计每个分组的取值和长度,筛选出符合条件的分组 group_info = df.groupby('group_id').agg( group_value=('all_answers', 'first'), group_length=('all_answers', 'count') ) target_groups = group_info[(group_info['group_value'] == 1) & (group_info['group_length'] == 5)].index # 生成New列 df['New'] = df.apply(lambda row: row['Answers'] if row['group_id'] in target_groups else 0, axis=1) # 移除辅助列(可选) df = df.drop('group_id', axis=1) print(df)
更简洁的实现方式:
用transform直接生成每个分组的长度,再通过where方法完成条件赋值,代码更紧凑:
import pandas as pd data = { 'Answers': [0.0, 0.0, 0.0, 1.0, -1.0, 1.0, -1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0], 'all_answers': [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1], 'Score': [72, 73, 74, 1, 2, 3, 4, 5, 1, 2, 1, 1, 2, 1, 1, 2, 1] } df = pd.DataFrame(data) # 生成分组ID和每个分组的长度 df['group_id'] = df['all_answers'].ne(df['all_answers'].shift()).cumsum() df['group_length'] = df.groupby('group_id')['all_answers'].transform('count') # 条件赋值生成New列 df['New'] = df['Answers'].where((df['all_answers'] == 1) & (df['group_length'] == 5), 0) # 移除辅助列 df = df.drop(['group_id', 'group_length'], axis=1) print(df)
内容的提问来源于stack exchange,提问作者Genry
相关产品推荐
相关产品推荐

