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

纯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])

核心实现逻辑

  1. 合并多输入数组的有效值:非0且非NaN视为有效,同位置有多个有效值时取传入顺序中第一个出现的值
  2. 向量化识别分组边界,定位每个分组的首个有效位置
  3. 对有效值按分组做前向填充生成目标数组

完整实现代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 09:24:09