R - dplyr - 按列分组并计算总和,如果给定组只有NA,则保留NA

3
我有一个数据框,第一列中存在重复的id,并且随后的列中存在不同的值。我想将此数据截断为每个唯一id仅有一条记录,并且随后列中的值是这些值的总和。然而,我可以使用dplyr::summarise完成此操作,但如果我使用na.rm = TRUE,则会将NA替换为0(如果所有记录都为NA),或者如果我没有使用它,则会将其求和为NA(如果出现NA)。

如何使其保留NA作为新值(如果所有值均为NA),并且对于存在数字值的NA,则进行求和。

对于糟糕的解释表示歉意。不确定如何更好地表述。

模拟数据框如下:

    df <- structure(
      list(
        id = structure(
          c(1L, 1L, 1L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 5L, 6L, 7L, 7L), 
          .Label = c("a", "b", "c", "d", "e", "f", "g"), 
          class = "factor"
        ), 
        `1` = c(NA, NA, NA, 1, 1, 0, 1, 1, 0, 1, NA, 1, NA, 0, 1, 0),
        `2` = c(NA, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, NA, 0), 
        `3` = c(NA, 1, 1, 0, 1, 1, 0, 1, 0, 1, NA, 1, 0, 0, NA, NA)
      ), 
      row.names = c(NA, -16L), 
      class = "data.frame"
    )

这将会打印出类似于这样的内容:

> df
   id  1  2  3
1   a NA NA NA
2   a NA  0  1
3   a NA  1  1
4   b  1  0  0
5   b  1  1  1
6   c  0  0  1
7   c  1  1  0
8   c  1  0  1
9   c  0  1  0
10  c  1  1  1
11  c NA  0 NA
12  d  1  1  1
13  e NA  0  0
14  f  0  0  0
15  g  1 NA NA
16  g  0  0 NA

我想按'id'列进行分组,然后对其求和,得到类似于以下的结果:
  id  1 2  3
1  a NA 1  2
2  b  2 1  1
3  c  3 3  3
4  d  1 1  1
5  e NA 0  0
6  f  0 0  0
7  g  1 0 NA

我尝试过使用summarise并加上na.rm=T,但它并没有提供我所需的内容。
    df %>% 
      group_by(
        id
      ) %>% 
      summarise_at(
        c(
          1,2,3
        ),
        sum,
        na.rm = T
      ) 

# A tibble: 7 x 4
  id      `1`   `2`   `3`
  <fct> <dbl> <dbl> <dbl>
1 a         0     1     2
2 b         2     1     1
3 c         3     3     3
4 d         1     1     1
5 e         0     0     0
6 f         0     0     0
7 g         1     0     0

不使用 na.rm = T:

    
    df %>% 
      group_by(
        id
      ) %>% 
      summarise_at(
        c(
          1,2,3
        ),
        sum
      ) 

# A tibble: 7 x 4
  id      `1`   `2`   `3`
  <fct> <dbl> <dbl> <dbl>
1 a        NA    NA    NA
2 b         2     1     1
3 c        NA     3    NA
4 d         1     1     1
5 e        NA     0     0
6 f         0     0     0
7 g         1    NA    NA

我不确定还有什么其他的尝试方法。任何建议都将不胜感激。非常感谢。

2个回答

1
您可以检查每个id中的值,如果所有值都为NA,则返回NA
library(dplyr)

df %>% 
  group_by(id) %>% 
  summarise(across(`1`:`3`, ~if(all(is.na(.))) NA else sum(., na.rm = TRUE)))
  #summarise_at(vars(`1`:`3`), ~if(all(is.na(.))) NA else sum(., na.rm = TRUE))

#   id      `1`   `2`   `3`
#  <fct> <dbl> <dbl> <dbl>
#1 a        NA     1     2
#2 b         2     1     1
#3 c         3     3     3
#4 d         1     1     1
#5 e        NA     0     0
#6 f         0     0     0
#7 g         1     0    NA

1
我们可以使用。
library(dplyr)
df %>%
    group_by(id) %>%
    summarise(across(-id, ~ if(sum(is.na(.)) == n() NA else sum(., na.rm = TRUE))) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接