在dplyr变异中使用sum函数

时间:2019-03-30 05:53:55

标签: r dplyr

我正在尝试在dplyr的mutate函数中使用sum函数。但是,我最终得到了意外的结果。下面是重现该问题的代码

chk1 <- data.frame(ba_mat_x=c(1,2,3,4),ba_mat_y=c(NA,2,NA,5))

我使用下面的代码创建了另一列,对以上两列进行汇总

chk2 <- chk1 %>% dplyr::mutate(ba_mat=sum(ba_mat_x+ba_mat_y,na.rm = T))

我使用na.rm=T是因为我在变量NA中有ba_mat_y个。我得到的结果如下

        ba_mat_x ba_mat_y ba_mat
   1        1       NA     13
   2        2        2     13
   3        3       NA     13
   4        4        5     13

但是,预期结果是

      ba_mat_x ba_mat_y ba_mat
1        1       NA     1
2        2        2     4
3        3       NA     3
4        4        5     9

3 个答案:

答案 0 :(得分:2)

您想要rowSums,以获取每一行的列总和。

> chk1 %>% dplyr::mutate(ba_mat = rowSums(., na.rm=T))

  ba_mat_x ba_mat_y ba_mat
1        1       NA      1
2        2        2      4
3        3       NA      3
4        4        5      9

您的其他表述(sum(ba_mat_x+ba_mat_y,na.rm = T)))表示:

  • 首先执行chk1$ba_mat_x + chk1$ba_mat_y1 + NA, 2 + 2, 3 + NA, 4 + 5,结果为NA, 4, NA, 9
  • 然后采用其中的sum(na.rm=T),即13

答案 1 :(得分:1)

如果我们有多个列,并且只想对有限的列求和,我们可以将它们替换为0,然后添加列

<button type="submit" class="btn btn-primary">Submit</button>

我们还可以使用library(dplyr) chk1 %>% mutate_at(vars(ba_mat_x,ba_mat_y), ~ replace(., is.na(.), 0)) %>% mutate(ba_mat = ba_mat_x + ba_mat_y) # ba_mat_x ba_mat_y ba_mat #1 1 0 1 #2 2 2 4 #3 3 0 3 #4 4 5 9 中的replace_na来做同样的事情。

tidyr

如果我们要使用chk1 %>% mutate_at(vars(ba_mat_x, ba_mat_y), tidyr::replace_na, 0) %>% mutate(ba_mat = ba_mat_x + ba_mat_y) ,另一种选择是使用sum的{​​{1}}或purrr,现在我们可以传递要添加的列列表,然后使用pmap

pmap_dbl

在这种情况下,我们也可以使用sum

chk1 %>%
  mutate(ba_mat = purrr::pmap_dbl(list(ba_mat_x, ba_mat_y), sum, na.rm = TRUE)) 

#  ba_mat_x ba_mat_y ba_mat
#1        1       NA      1
#2        2        2      4
#3        3       NA      3
#4        4        5      9

这也将起作用,因为我们只有两列,但是如果有更多的列,使用map2_dbl选项会更好/更安全。


此外,就您的尝试而言,如果您将chk1 %>% mutate(ba_mat = purrr::map2_dbl(ba_mat_x, ba_mat_y, sum, na.rm = TRUE)) 添加到它,它将可以正常工作。顾名思义,pmap以行方式进行所有操作。

rowwise

但是rowwise通常较慢。

答案 2 :(得分:1)

我们可以使用rowSums中的base R

chk1$ba_mat <- rowSums(chk1, na.rm = TRUE)
chk1
#   ba_mat_x ba_mat_y ba_mat
#1        1       NA      1
#2        2        2      4
#3        3       NA      3
#4        4        5      9

或使用tidverse,同时保持原始列不变

library(tidyverse)
chk1 %>% 
    mutate(ba_mat  = replace(., is.na(.), 0) %>%
                     reduce(`+`))
#    ba_mat_x ba_mat_y ba_mat
#1        1       NA      1
#2        2        2      4
#3        3       NA      3
#4        4        5      9

或与case_when

chk1 %>% 
    mutate_if(is.numeric, list(new = ~case_when(is.na(.) ~ 0,
                TRUE ~ .))) %>%
    transmute(!!! rlang::syms(names(chk1)), ba_mat = ba_mat_x_new + ba_mat_y_new)
#   ba_mat_x ba_mat_y ba_mat
#1        1       NA      1
#2        2        2      4
#3        3       NA      3
#4        4        5      9