变异和行求和排除列

6
与之相似:mutate rowSums exclude one column,但在我的情况下,我真的想使用select来删除一个特定的列或一组列。 我试图理解为什么这种方法是行不通的。
d <- data.frame(
   Alpha = letters[1:26], 
   Beta = rnorm(26),
   Epsilon = rnorm(26),
   Gamma = rnorm(26)
)

我以为这会起作用,但它给了我一个奇怪的错误提示:
# Total = Beta + Gamma
d <- mutate(d,Total = rowSums(select(d,-Epsilon,-Alpha)))

Error: All select() inputs must resolve to integer column positions.
The following do not:
*  -structure(1:26, .Label = c("a", "b", "c", "d", "e", "f", "g", "h", "i...
In addition: Warning message:
In Ops.factor(1:26) : ‘-’ not meaningful for factors

我希望能够在长链中完成此操作,并保持“dplyr风格”... 让我感到奇怪的是,尽管不使用典型的dplyr语法,这实际上非常简单,但这样做很困难:

d$Total <- rowSums(select(d, -Alpha, -Epsilon)) # This works! 

2
我认为这很难做,基于这个 - akrun
1
我猜你可以通过 mutate(d, Total = d %>% .[c("Beta", "Gamma")] %>% rowSums) 来处理,但那只是基本上像使用 transform()mutate(),我不认为那比 rowSums(d[c("Beta", "Gamma")]) 更好。 - Rich Scriven
dplyr_0.7.6 中,上述语法 mutate(d,Total = rowSums(select(d,-Epsilon,-Alpha))) 似乎可以工作(至少对我来说是这样)。 - tjebo
2个回答

4

@akrun 已经提供了一个有关这个问题的相关链接。至于 dplyr 的解决方案,我建议使用 do

d %>%
  do({
    .$Total <- rowSums(select(., -Epsilon, -Alpha))
    .
  })

这很好,但是使用 do 相对于常规的 rowSums 而言会更慢,而且不需要任何软件包。 - akrun
@akrun,如果它(指另一种解决方案)能够工作,那么它会比“mutate”解决方案慢吗?为什么? - Tim
根据一些对于其他情况下 mutatedo 的基准测试,我认为它可能会很慢。但是,您可以在一个包含 1e6 数据集的独立 rowSums 中进行基准测试,在 mutatedo 内部进行基准测试。 - akrun
我不处理大量数据,所以这个答案对我的目的足够了。 - Brandon Bertelsen

3

我刚开始学习dplyr,可能是因为版本升级的原因,但是以下代码现在无法正常工作:

d %>% mutate(Total=rowSums(select(d,-Epsilon, -Alpha)))

现在,我经常看到人们使用点记法:

d %>% mutate(Total=rowSums(select(.,-Epsilon, -Alpha)))

稍微容易处理一些的例子:

df2 = data.frame(A=sample(0:20,10), B=sample(0:20, 10), C=sample(0:20,10), D=LETTERS[1:10])
df2
    A  B  C D
1  19  0  9 A
2   6 10 14 B
3  13 20  6 C
4  20  4 15 D
5   9 14  8 E
6  11  1 18 F
7   4 15 13 G
8  17  5  0 H
9  16  3 16 I
10  2  6  1 J
df2 %>% mutate(total=rowSums(select(.,-D)))
    A  B  C D total
1  19  0  9 A    28
2   6 10 14 B    30
3  13 20  6 C    39
4  20  4 15 D    39
5   9 14  8 E    31
6  11  1 18 F    30
7   4 15 13 G    32
8  17  5  0 H    22
9  16  3 16 I    35
10  2  6  1 J     9

注意:
你链接的问题有一个更新的答案,展示了一种演示了一些新的dplyr特性的新方法:

df2 %>% mutate(total=rowSums(select_if(., is.numeric)))
    A  B  C D total
1  19  0  9 A    28
2   6 10 14 B    30
3  13 20  6 C    39
4  20  4 15 D    39
5   9 14  8 E    31
6  11  1 18 F    30
7   4 15 13 G    32
8  17  5  0 H    22
9  16  3 16 I    35
10  2  6  1 J     9

1
是的,现在你也可以使用 { some_fun(.) },这使得它甚至更容易。尤其是对于没有将输入作为第一个函数的函数(如grep*)。 - Brandon Bertelsen

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