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

R语言基于列索引条件对含NA的dataframe列求和方法咨询

R 数据框按条件列求和解决方案

函数修正实现

首先注意不要使用str作为函数名,会与R基础包自带的结构查看函数str()冲突,修正后的完整函数如下:

calc_adj_agg <- function(df, overwrite = TRUE, na.rm = TRUE){
    # 匹配目标列并按年份升序排序,避免列顺序错乱
    nms <- grep("adj_avg_[0-9]+$", names(df), value = TRUE)
    nms <- nms[order(as.integer(sub("adj_avg_", "", nms)))]
    # 生成新列名
    revnms <- gsub("adj_avg", "agg_pass1", nms)
    if(!overwrite) {
        revnms <- setdiff(revnms, names(df))
        # 过滤对应要计算的原始列
        nms <- nms[gsub("adj_avg", "agg_pass1", nms) %in% revnms]
    }
    # 按规则计算求和值
    df[, revnms] <- lapply(seq_along(nms), function(i){
        cur_col <- df[[nms[i]]]
        if(i == 1){
            # 首列直接求和
            sum_val <- sum(cur_col, na.rm = na.rm)
        } else {
            prev_col <- df[[nms[i-1]]]
            # 筛选当前列和前一列均非NA的行求和
            valid_idx <- !is.na(cur_col) & !is.na(prev_col)
            sum_val <- sum(cur_col[valid_idx], na.rm = na.rm)
        }
        # 求和结果填充整列
        rep(sum_val, nrow(df))
    })
    return(df)
}

lapply 逻辑说明

你原来的写法是直接遍历列数据,无法获取前一列的对应值,因此改为遍历列的索引位置:

  • 当索引为1时,对应首列直接对全列求和
  • 索引大于1时,先提取当前列和前一列的向量,取两者同时非NA的行索引,再对当前列的有效行求和
  • 最后将求和得到的单个值重复n次(n为数据框行数),填充为新列

更简便的实现方式

如果你使用tidyverse生态,可通过dplyr+purrr实现更简洁的代码,性能与基础包写法基本一致:

library(dplyr)
library(purrr)

calc_adj_agg_tidy <- function(df, overwrite = TRUE, na.rm = TRUE){
    nms <- grep("adj_avg_[0-9]+$", names(df), value = TRUE)
    nms <- nms[order(as.integer(sub("adj_avg_", "", nms)))]
    revnms <- gsub("adj_avg", "agg_pass1", nms)
    if(!overwrite) {
        revnms <- setdiff(revnms, names(df))
        nms <- nms[gsub("adj_avg", "agg_pass1", nms) %in% revnms]
    }
    # 生成求和规则的命名列表
    sum_rules <- set_names(
        map(seq_along(nms), function(i){
            if(i == 1){
                ~sum(.data[[nms[i]]], na.rm = na.rm)
            } else {
                ~sum(.data[[nms[i]]][!is.na(.data[[nms[i]]]) & !is.na(.data[[nms[i-1]]])], na.rm = na.rm)
            }
        }),
        revnms
    )
    # 批量生成新列
    df %>% mutate(!!!sum_rules)
}

效果验证

使用你提供的示例数据运行函数,得到的各年求和结果如下:

  • agg_pass1_2016:131561293.9
  • agg_pass1_2017:138895480.3
  • agg_pass1_2018:133534898.2
  • agg_pass1_2019:133108702.6
  • agg_pass1_2020:136639690.1
    完全符合你描述的计算规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:36:01