如何查找列表中非NaN连续值组的首尾索引
查找DataFrame中非NaN连续值分组的首尾索引
需求:需要筛选出DataFrame中非NaN连续值的分组,返回每组首尾元素的索引。例如对应序列[NaN, NaN, 4, 63, 34, NaN, NaN, NaN, 234, 3, NaN],应返回[[2,4],[8,9]]。
以下是你已实现的可用函数:
def find_groups_indexes(db): groups_indexes = [] for i in range(len(db)-1): if db.iloc[i].isnull().all()==True and db.iloc[i+1].isnull().all()==False: subgroup=[i+1] if db.iloc[i].isnull().all()==False and db.iloc[i+1].isnull().all()==True: subgroup.append(i) groups_indexes.append(subgroup) subgroup=[] print('\ngroups = ', groups_indexes) return groups_indexes
更简便的实现方式
可以利用pandas的矢量化操作替代手动循环,代码更简洁且效率更高,同时能覆盖边界场景(比如开头/结尾就是非NaN的情况):
import pandas as pd def find_groups_indexes_simpler(df): # 生成每行是否全非NaN的布尔序列 not_nan_rows = df.notna().all(axis=1) # 为连续的非NaN行分配唯一分组ID group_ids = not_nan_rows.cumsum() * not_nan_rows # 过滤掉全NaN的分组,仅保留有效分组的索引 valid_group_indexes = group_ids[group_ids != 0] # 按分组ID聚合,提取每组的首尾索引 return valid_group_indexes.groupby(group_ids).agg(['first', 'last']).values.tolist()
代码说明:
df.notna().all(axis=1):判断每行是否所有元素都非NaN,得到布尔序列。not_nan_rows.cumsum() * not_nan_rows:通过累加操作给连续的非NaN行分配递增的分组ID,全NaN行的ID为0。- 过滤掉ID为0的行后,按分组ID聚合,直接获取每组的第一个和最后一个索引,转换为列表格式返回。
这个方法无需手动遍历每行判断状态切换,依赖pandas的内置优化,处理大数据集时性能优势更明显,同时能正确处理原函数可能遗漏的边界情况(比如整个DataFrame都无NaN,或者首尾段是非NaN的情况)。
内容的提问来源于stack exchange,提问作者grimad
相关产品推荐
相关产品推荐

