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

如何用Pandas筛选DataFrame中start与end标记间的行(含标记行)

筛选每组start到end之间的行(含首尾)

针对你给出的DataFrame,这里提供两种可行的解决方案,实现按record_id分组后,保留每组内start到end标记之间的所有行(包含start和end行):

方法一:利用累积和标记区间

这种方法通过数值标记和分组累积和快速定位目标区间,效率较高:

import pandas as pd
import numpy as np

# 构建示例数据
data = {'record_id' : [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3],
        'some_data': ['semper', 'lectus', 'turpis', 'proin', 'justo', 'vitae', 'luctus', 'magna', 'non', 'vestibulum', 'nulla', 'erat', 'nisl', 'orci', 'curae', 'nam', 'aliquet', 'aliquam', 'cum', 'convallis'],
        'boundaries': [np.NaN, 'start', np.NaN, np.NaN, 'end', np.NaN, np.NaN, np.NaN, 'start', np.NaN, np.NaN, 'end', np.NaN, np.NaN, np.NaN, 'start', np.NaN, 'end', np.NaN, np.NaN]}
df = pd.DataFrame(data)

# 1. 给start和end赋值标记值,其余补0
df['marker'] = df['boundaries'].map({'start': 1, 'end': -1}).fillna(0)

# 2. 按record_id分组计算累积和,start后累积和为1,遇到end后变为0
df['in_range'] = df.groupby('record_id')['marker'].cumsum()

# 3. 保留累积和>=1的行,同时单独标记end行(因为end行的累积和为0)
df['in_range'] = df['in_range'].astype(bool) | (df['boundaries'] == 'end')

# 4. 筛选结果并移除辅助列
result = df[df['in_range']].drop(columns=['marker', 'in_range'])
print(result)

方法二:直接定位start/end索引标记区间

这种方法逻辑更直观,适合理解区间标记的过程:

import pandas as pd
import numpy as np

# 构建示例数据(同上)
data = {'record_id' : [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3],
        'some_data': ['semper', 'lectus', 'turpis', 'proin', 'justo', 'vitae', 'luctus', 'magna', 'non', 'vestibulum', 'nulla', 'erat', 'nisl', 'orci', 'curae', 'nam', 'aliquet', 'aliquam', 'cum', 'convallis'],
        'boundaries': [np.NaN, 'start', np.NaN, np.NaN, 'end', np.NaN, np.NaN, np.NaN, 'start', np.NaN, np.NaN, 'end', np.NaN, np.NaN, np.NaN, 'start', np.NaN, 'end', np.NaN, np.NaN]}
df = pd.DataFrame(data)

# 定义分组处理函数:标记每组内start到end的区间
def mark_target_interval(group):
    # 获取当前组内start和end的索引
    start_indices = group[group['boundaries'] == 'start'].index
    end_indices = group[group['boundaries'] == 'end'].index
    # 创建全False的掩码
    mask = pd.Series(False, index=group.index)
    # 遍历每一组start-end对,标记区间内的行
    for s_idx, e_idx in zip(start_indices, end_indices):
        mask.loc[s_idx:e_idx] = True
    return mask

# 按record_id分组应用函数,生成标记列
df['in_range'] = df.groupby('record_id').apply(mark_target_interval).reset_index(level=0, drop=True)

# 筛选结果并移除辅助列
result = df[df['in_range']].drop(columns='in_range')
print(result)

两种方法最终都会得到如下结果:

record_id  some_data boundaries
1           1     lectus       start
2           1     turpis        NaN
3           1      proin        NaN
4           1       justo         end
8           2        non       start
9           2  vestibulum        NaN
10          2       nulla        NaN
11          2        erat         end
15          3        nam       start
16          3    aliquet        NaN
17          3    aliquam         end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:47:04