如何用Pandas按特定值提取边界范围内的行组?
数据
我的数据如下所示:
import pandas as pd df = pd.DataFrame( [ ["start", ""], ["data", 10], ["data", 11], ["stop", ""], ["start", ""], ["data", 20], ["data", 21], ["stop", ""], ], columns=["type", "value"], )
对应的DataFrame输出:
type value 0 start 1 data 10 2 data 11 3 stop 4 start 5 data 20 6 data 21 7 stop
目标
我的目标是遍历由start和stop界定的data纯列表:
[10, 11] [20, 21]
为此,我希望能遍历通过特定列中特定值定位到的DataFrame分组。
尝试方案
我可以通过迭代实现需求:
def iter_groups(df): start_idx = None for idx, row in df.iterrows(): if row["type"] == "start": assert start_idx is None start_idx = idx continue if row["type"] == "stop": assert start_idx is not None yield df.iloc[start_idx : idx+1] start_idx = None
但这种方法速度很慢。如何使用Pandas原生方法实现该需求?
简化假设
可以确定的是,一个分组的stop行与下一个分组的start行之间没有其他行。
解决方案
利用Pandas的向量化操作生成分组ID,再通过分组实现需求,效率远高于迭代:
方法1:提取data值的列表
# 生成分组ID:每遇到一次start,分组ID递增 df['group_id'] = (df['type'] == 'start').cumsum() # 过滤出data行,按分组ID聚合为值列表 data_groups = df[df['type'] == 'data'].groupby('group_id')['value'].apply(list).tolist() print(data_groups) # 输出:[[10, 11], [20, 21]]
方法2:遍历完整的分组DataFrame(包含start、data、stop行)
如果需要遍历每个完整的start-stop块:
df['group_id'] = (df['type'] == 'start').cumsum() for group_id, group_df in df.groupby('group_id'): print(f"分组 {group_id}:") print(group_df)
输出结果:
分组 1: type value group_id 0 start 1 1 data 10 1 2 data 11 1 3 stop 1 分组 2: type value group_id 4 start 2 5 data 20 2 6 data 21 2 7 stop 2
原理说明
(df['type'] == 'start').cumsum()会对type等于start的行标记为1,其余为0,累加后生成连续的分组ID,每个start到下一个start前的所有行会被分配同一个ID,从而实现高效分组。这种操作是Pandas原生的向量化计算,比逐行迭代快几个数量级,尤其适合处理大数据集。
内容的提问来源于stack exchange,提问作者Jonathon Reinhart
相关产品推荐
相关产品推荐

