使用'mutate_'逐行对一堆列求和

12

在这篇博客文章中,Paul Hiemstra展示了如何使用 dplyr::mutate_对两列进行求和。以下是相关部分的复制粘贴:

library(lazyeval)
f = function(col1, col2, new_col_name) {
    mutate_call = lazyeval::interp(~ a + b, a = as.name(col1), b = as.name(col2))
    mtcars %>% mutate_(.dots = setNames(list(mutate_call), new_col_name))
}

允许执行以下操作:

head(f('wt', 'mpg', 'hahaaa'))

太棒了!

我在评论中提出了一个问题,就是如何将这个方法扩展到100列,因为对我来说不太清楚,如果不使用上述的方法,怎么能做到而不必键入所有名称。保罗很好心地回答了我的问题(谢谢!):

# data
df = data.frame(matrix(1:100, 10, 10))
names(df) = LETTERS[1:10]

# answer
sum_all_rows = function(list_of_cols) {
  summarise_calls = sapply(list_of_cols, function(col) {
    lazyeval::interp(~col_name, col_name = as.name(col))
  })
  df %>% select_(.dots = summarise_calls) %>% mutate(ans1 = rowSums(.))
}
sum_all_rows(LETTERS[sample(1:10, 5)])

我想在以下几个方面改进这个答案:

  1. 其他列已经消失了,我想保留它们。

  2. 它使用rowSums(),这需要将data.frame强制转换为matrix,我希望避免这种情况。

    此外,我不确定在非do()动词中使用.是否被鼓励。因为当与group_by()一起使用时,mutate()中的.似乎不仅适用于那些行。

  3. 最重要的是,如何使用mutate_()而不是mutate()来完成相同的工作?

我找到了这个答案,它解决了第一点,但不幸的是,两个dplyr答案都使用了rowSums()mutate()


PS: 我刚刚阅读了那个答案下的Hadley的评论。如果我理解正确,“重塑为长格式+按组合并+求和+重塑为宽格式”是这类操作的推荐dplyr方法吗?


当您明确限定其使用时,无需使用library(lazyeval) - Konrad Rudolph
1个回答

7
这里有一种不同的方法:
library(dplyr); library(lazyeval)
f <- function(df, list_of_cols, new_col) {
  df %>% 
    mutate_(.dots = ~Reduce(`+`, .[list_of_cols])) %>% 
    setNames(c(names(df), new_col))
}

head(f(mtcars, c("mpg", "cyl"), "x"))
#   mpg cyl disp  hp drat    wt  qsec vs am gear carb    x
#1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 27.0
#2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 27.0
#3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1 26.8
#4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1 27.4
#5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 26.7
#6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 24.1

关于您提出的几点:

  • 其他列被保留
  • 它不使用rowSums
  • 您在这里特别要求逐行操作,因此我不确定(但)group_by在使用mutate/mutate_中的.时会产生任何负面影响。
  • 它使用了mutate_

太好了!关于使用 group_by().,我觉得有点奇怪。比如说,计算行总和并将它们除以组内的最大总和。我猜你首先会计算行总和,然后按组进行分组并得出比率?如果是这样,我认为这样做有点奇怪(不能使用 mutate 一步完成,而必须使用 do())。但也许这是出于设计考虑,没关系。谢谢。 - Arun
嗨@docendo discimus。非常好的回答。您是否知道在最近的dplyr版本中是否有一些函数可以将匹配某个正则表达式的列的总和作为新列添加? - agenis

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