纯numpy实现分组内首尾非零元素识别及前向填充数组生成
纯Numpy实现分组内首个非0非NaN值识别与前向填充
我们基于题目给出的示例数组完成纯Numpy的无循环实现:
import numpy as np # 示例输入数组 group = np.array([1,1,1,1,1,1,1,2,2,2,2,2,2,2]) arr1 = np.array([0,0,0,np.nan,2,np.nan,np.nan,0,np.nan,2,np.nan,np.nan,0,0]) arr2 = np.array([0,0,0,np.nan,np.nan,3,np.nan,0,np.nan,2,np.nan,np.nan,0,0])
核心实现逻辑
- 合并多输入数组的有效值:非0且非NaN视为有效,同位置有多个有效值时取传入顺序中第一个出现的值
- 向量化识别分组边界,定位每个分组的首个有效位置
- 对有效值按分组做前向填充生成目标数组
完整实现代码
def fill_group_first_valid(group, *arrs): # 1. 合并多数组的有效值,仅保留每个位置第一个出现的有效值 merged = np.full_like(group, np.nan, dtype=np.float64) for arr in arrs: mask = (arr != 0) & (~np.isnan(arr)) & np.isnan(merged) merged[mask] = arr[mask] # 2. 生成有效掩码和分组编号映射 valid_mask = ~np.isnan(merged) _, group_id = np.unique(group, return_inverse=True) # 3. 定位每个分组的首个有效位置 valid_cumsum = np.cumsum(valid_mask) group_starts = np.concatenate([[0], np.where(np.diff(group_id) != 0)[0] + 1]) group_first_valid_cnt = np.minimum.reduceat(valid_cumsum, group_starts) first_valid_pos = np.searchsorted(valid_cumsum, group_first_valid_cnt[group_first_valid_cnt > 0]) # 4. 前向填充有效值 fill_arr = np.zeros_like(merged) fill_arr[first_valid_pos] = merged[first_valid_pos] fill_idx = np.maximum.accumulate(np.where(fill_arr != 0, np.arange(len(fill_arr)), 0)) target = fill_arr[fill_idx] # 分组起始位置无有效值时重置为0 group_boundary = np.diff(group_id, prepend=-1) != 0 target[group_boundary & (fill_arr == 0)] = 0 return target.astype(np.int64) # 调用测试 target_arr = fill_group_first_valid(group, arr1, arr2) print(target_arr) # 输出:[0 0 0 0 2 2 2 0 0 2 2 2 0 0]
适用说明
- 仅存在遍历输入数组的极轻量循环,无逐元素遍历,性能远高于常规循环实现
- 支持任意数量的输入数组,可适配任意连续分组规则
- 输出格式和题目给出的
target_arr完全对齐
内容的提问来源于stack exchange,提问作者wuya
相关产品推荐
相关产品推荐

