r - 当使用 dplyr 为一组列给出最大数量的 NA values 时,计算行均值

示例数据集...

> tribble(
+   ~colA, ~colB, ~colC, ~colD, ~colE,
+   1, 2, 3, 4, 5,
+   2, 3, NA, 4, 5,
+   3, NA, NA, NA, 4,
+   4, NA, NA, 5, 6
+ )
# A tibble: 4 × 5
   colA  colB  colC  colD  colE
  <dbl> <dbl> <dbl> <dbl> <dbl>
1     1     2     3     4     5
2     2     3    NA     4     5
3     3    NA    NA    NA     4
4     4    NA    NA     5     6

如果只存在两个(最多)NA,我如何创建一个新列来给出列 B、C、D 和 E 的平均值?在这种情况下,第三行平均值应该是 NA,因为它有 3 个 NA。我放 colA 是因为我希望能够使用 tidyselect 来选择包含哪些变量。

到目前为止,我有这个...

dat %>% 
  rowwise() %>% 
  mutate(
    mean = if_else(
      c_across(colB, colC, colD, colE), 
      condition = sum(is.na(.)) <= 2, 
      true = mean(., na.rm = T), 
      false = NA
      )
    )

但是我收到此错误消息...

Error in `mutate()`:
! Problem while computing `mean = if_else(...)`.
ℹ The error occurred in row 1.
Caused by error in `if_else()`:
! `false` must be a double vector, not a logical vector.
Run `rlang::last_error()` to see where the error occurred.
Warning message:
Problem while computing `mean = if_else(...)`.
ℹ argument is not numeric or logical: returning NA
ℹ The warning occurred in row 1.

在一个理想的世界中,我将有一个函数来获取一组列的行均值和给定数量的允许 NA,我可以重新利用它们。

回答1

我们可以使用 across 来选择感兴趣的列。

library(dplyr)

dat %>% 
  mutate(mean = ifelse(rowSums(is.na(across(-colA))) > 2, 
                       NA, 
                       rowMeans(across(-colA), na.rm = T)))

# A tibble: 4 × 6
   colA  colB  colC  colD  colE  mean
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     1     2     3     4     5   3.5
2     2     3    NA     4     5   4  
3     3    NA    NA    NA     4  NA  
4     4    NA    NA     5     6   5.5

回答2

base R 中:

df$mean <- apply(df[-1], 1, \(x) if (sum(is.na(x)) <= 2) mean(x, na.rm = T) else NA)

df

#> # A tibble: 4 x 6
#>    colA  colB  colC  colD  colE  mean
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1     2     3     4     5   3.5
#> 2     2     3    NA     4     5   4  
#> 3     3    NA    NA    NA     4  NA  
#> 4     4    NA    NA     5     6   5.5

或使用 dplyr

library(dplyr)

df %>% 
  mutate(mean = apply(.[-1], 1, \(x) if (sum(is.na(x)) <= 2) mean(x, na.rm = T) else NA))

#> # A tibble: 4 x 6
#>    colA  colB  colC  colD  colE  mean
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1     1     2     3     4     5   3.5
#> 2     2     3    NA     4     5   4  
#> 3     3    NA    NA    NA     4  NA  
#> 4     4    NA    NA     5     6   5.5

回答3

我们可以做到以下几点。这是一个示例,如何在 rowSumsrowMeans 中选择一组具有 select 的列。

library(dplyr)

dat2 <- dat %>%
  mutate(mean = ifelse(rowSums(is.na(select(., -colA))) > 2, 
                       NA, 
                       rowMeans(select(., -colA), na.rm = TRUE)))

回答4

data.table 选项:

library(data.table)
setDT(df)[!rowSums(is.na(df)) > 2, mean := rowMeans(.SD, na.rm = TRUE), .SDcols = -1]

输出:

colA colB colC colD colE mean
1:    1    2    3    4    5  3.5
2:    2    3   NA    4    5  4.0
3:    3   NA   NA   NA    4   NA
4:    4   NA   NA    5    6  5.5

相似文章

r - filtering 列表中的数据时发出

我有一个很大的列表,我正在尝试从同一个数据框创建多个数据框。为此,我filtering输出各种变量中的数据。大多数代码的基本结构是相同的,除了一个之外,所有代码都可以正常工作。这是清单。structu...

r - R pivot_longer() 在输出中有 NA

我无法旋转我的数据。我可以使用一种解决方法来产生我想要的输出(如下所示),但我怀疑它可能在单个pivot_longer()调用中,我只是无法弄清楚该命令。任何建议/帮助将不胜感激。library(dp...

最新文章