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

R语言实现非NA列随机抽样行均值及NA异常处理

问题:按行随机抽取非NA值计算均值(处理不同NA数量的行)

我有一个数据框,需求是为每一行随机抽取3个非NA列(各行抽取的列可以不同),并计算这3个抽样值的均值。数据框中存在大量全NA、仅含1个或2个非NA值的行,且无法删除这些行。

我尝试了以下代码:

df_new <- df %>%
  rowwise %>%
  mutate(inflo_mean = mean(sample(na.omit(c_across(everything())), 3)))

运行后出现报错:

Error in `mutate()`:
ℹ In argument: `inflo_mean = mean(sample(na.omit(c_across(everything())), 3))`.
ℹ In row 1.
Caused by error in `sample.int()`:
! invalid first argument

之后我拆分步骤,针对不同NA情况处理,编写了如下代码:

df_new2 <- df %>%
  rowwise() %>%
  mutate(num_NAs = sum(!is.na(across(starts_with("Col_")))),
         v_inflo = list(na.omit(c_across((starts_with("Col_"))))),
         inflo_mean = case_when(num_NAs > 2 ~ mean(sample(v_inflo, 3)),
                                  num_NAs == 2 ~ mean(v_inflo),
                                  num_NAs == 1 ~ as.numeric(v_inflo),
                                  num_NAs == 0 ~ NA_real_,
                                  TRUE ~ NA_real_))

但仍出现相同错误。我已确认所有列均为整数类型,请问问题出在哪里?是否有其他解决方案?

示例数据:

> dput(df)
structure(list(Col_1 = c(NA, 77L, 82L, 172L), Col_2 = c(NA, 79L, 
NA, 135L), Col_3 = c(NA, 81L, NA, 131L), Col_4 = c(NA_integer_, 
NA_integer_, NA_integer_, NA_integer_), Col_5 = c(NA, NA, NA, 
33L), Col_6 = c(NA, NA, NA, 104L), Col_7 = c(NA, NA, NA, 106L
), Col_8 = c(NA, NA, NA, 93L), Col_9 = c(NA, NA, NA, 50L), Col_10 = c(NA, 
NA, NA, 48L), Col_11 = c(NA, NA, NA, 96L), Col_12 = c(NA_integer_, 
NA_integer_, NA_integer_, NA_integer_), Col_13 = c(NA_integer_, 
NA_integer_, NA_integer_, NA_integer_), Col_14 = c(NA_integer_, 
NA_integer_, NA_integer_, NA_integer_), Col_15 = c(NA_integer_, 
NA_integer_, NA_integer_, NA_integer_)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -4L))

问题根源

报错出现在全NA行:当na.omit(c_across(...))返回空向量时,sample()函数接收空向量作为第一个参数,会触发invalid first argument错误。即使你在case_when里判断了num_NAs == 0 ~ NA_real_,但case_when会评估所有分支(非短路执行),全NA行仍会执行sample(v_inflo, 3),此时v_inflo是空列表,直接触发错误。

解决方案

方案1:使用if/else短路逻辑(推荐)

if/else是短路执行的,只有满足条件的代码块会被运行,避免空向量传入sample():

df_final <- df %>%
  rowwise() %>%
  mutate(
    non_na_vals = list(na.omit(c_across(starts_with("Col_")))),
    inflo_mean = {
      len <- length(non_na_vals)
      if (len == 0) {
        NA_real_
      } else if (len == 1) {
        as.numeric(non_na_vals)
      } else if (len == 2) {
        mean(non_na_vals)
      } else {
        mean(sample(non_na_vals, 3))
      }
    },
    non_na_vals = NULL  # 可选:删除临时列
  ) %>%
  ungroup()  # 取消行分组,恢复常规数据框操作效率

方案2:给sample添加安全长度判断

在sample中用min(3, length(v_inflo))确保抽样数量不超过非NA值的长度,同时将全NA行的判断放在case_when最前面(减少无效评估):

df_final <- df %>%
  rowwise() %>%
  mutate(
    num_NAs = sum(!is.na(across(starts_with("Col_")))),
    v_inflo = list(na.omit(c_across(starts_with("Col_")))),
    inflo_mean = case_when(
      num_NAs == 0 ~ NA_real_,
      num_NAs == 1 ~ as.numeric(v_inflo),
      num_NAs == 2 ~ mean(v_inflo),
      num_NAs > 2 ~ mean(sample(v_inflo, min(3, length(v_inflo)))),
      TRUE ~ NA_real_
    )
  ) %>%
  ungroup()

内容的提问来源于Stack Exchange,提问作者Em Laskey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 09:00:22