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

如何基于ID列交替删除分组内的连续行并保留指定行?

解决方案:分组内交替删除连续行并保留指定行

问题场景

原数据集示例:

group   ID  
ABCDE   2   
ABCDE   3   
ABCDE   4   
ABCDE   5   
ABCDE   6   
ABCDE   22  

预期输出:

group  ID  result
ABCDE   3   Keep
ABCDE   5   Keep
ABCDE   22  Keep

核心需求:在同一分组内,对连续ID构成的序列执行交替删除(删除第1、3、5...位的行),非连续的单独行直接保留。


Python(Pandas)实现方案

import pandas as pd

# 构造示例数据
data = {
    'group': ['ABCDE'] * 6,
    'ID': [2, 3, 4, 5, 6, 22]
}
df = pd.DataFrame(data)

def process_group(group_df):
    # 标记当前ID与上一个是否连续
    group_df['is_consecutive'] = group_df['ID'].diff().fillna(1) == 1
    # 生成连续块的唯一标识(不连续处分割)
    group_df['block'] = (~group_df['is_consecutive']).cumsum()
    # 计算每行在所属连续块内的位置(从0开始计数)
    group_df['block_pos'] = group_df.groupby('block').cumcount()
    
    # 标记保留/删除:连续块长度>1时,保留块内位置为奇数的行;单独行直接保留
    group_df['result'] = 'Keep'
    drop_mask = (group_df.groupby('block')['ID'].transform('size') > 1) & (group_df['block_pos'] % 2 == 0)
    group_df.loc[drop_mask, 'result'] = 'Drop'
    
    return group_df

# 分组处理并筛选结果
processed_df = df.groupby('group', group_keys=False).apply(process_group)
final_df = processed_df[processed_df['result'] == 'Keep'].drop(columns=['is_consecutive', 'block', 'block_pos'])

print(final_df)

关键逻辑说明

  1. 连续块识别:通过ID.diff()计算相邻ID的差值,判断是否连续;用cumsum()将不连续的位置作为分割点,生成连续块的编号。
  2. 块内位置标记:用cumcount()统计每行在所属连续块内的索引位置。
  3. 保留规则:连续块中,删除位置为偶数(从0开始)的行(对应原序列的第1、3、5...位);长度为1的单独块直接保留。

R(dplyr)实现方案

library(dplyr)

# 构造示例数据
df <- tibble(
  group = rep("ABCDE", 6),
  ID = c(2, 3, 4, 5, 6, 22)
)

final_df <- df %>%
  group_by(group) %>%
  mutate(
    # 标记是否连续(第一行默认连续)
    is_consecutive = c(TRUE, diff(ID) == 1),
    # 生成连续块标识
    block = cumsum(!is_consecutive),
    # 计算每行在块内的位置(从1开始计数)
    block_pos = row_number() - match(block, block) + 1
  ) %>%
  group_by(group, block) %>%
  mutate(
    # 连续块内删除奇数位置的行,其余保留
    result = ifelse(n() > 1 & block_pos %% 2 == 1, "Drop", "Keep")
  ) %>%
  ungroup() %>%
  filter(result == "Keep") %>%
  select(-is_consecutive, -block, -block_pos)

print(final_df)

关键逻辑说明

  1. 连续块识别:用diff(ID)判断相邻ID是否连续,cumsum(!is_consecutive)生成块编号。
  2. 块内位置计算:通过row_number()和match()计算每行在块内的位置(从1开始)。
  3. 保留规则:连续块中删除位置为奇数的行,单独块直接保留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:43:11