如何从一组特定的列中整理(tidy)行数据?

4

我希望能够从数据框的多个列中计算汇总变量。当打出所有行名时,这是可能的,但我想使用starts_with()和类似的函数。

df <- data.frame(A1 = rnorm(100, 0, 1),
                 A2 = rnorm(100, 0, 1),
                 A3 = rnorm(100, 0, 1),
                 B1 = rnorm(100, 0, 1),
                 B2 = rnorm(100, 0, 1))

适用的方法:

library(tidyverse)
df %>% mutate(A = (A1 + A2 + A3)/3)
df %>% mutate(A = rowMeans(select(., A1:A3)))

然而,当汇总多个变量时,前者会变得很烦人,而当汇总多行时,后者会变得非常缓慢。我怀疑必须有更快的解决方案。
不起作用的方法:
df %>% mutate(A = mean(A1:A3))
df %>% group_by(row_number()) %>% mutate(A = mean(A1:A3))
df %>% group_by(row_number()) %>% mutate(A = mean(starts_with("A")))

我的问题是:有没有一种方法可以在mutate()中使用mean()等函数来计算行均值,最好不必拼写每个变量?

3个回答

5

在您的select函数中使用starts_with函数:

df %>% mutate(A = rowMeans(select(., starts_with("A"))))

如果你搜索 select_helpers 的帮助文档,你会找到更多相关内容。

谢谢您的回答。这本质上是我的第二个“有效”的示例,只不过使用了starts_with()。不幸的是,这会变得非常慢,所以我希望有更快的解决方案。 - simoncolumbus
1
抱歉,我错过了性能部分! - ricoderks

4

在我的测试中,基本的R语言是最快的。
我将使用一个更大的数据框。

library(tidyverse)
library(microbenchmark)
library(ggplot2)

set.seed(1234)

n <- 1e4
df <- data.frame(A1 = rnorm(n, 0, 1),
                 A2 = rnorm(n, 0, 1),
                 A3 = rnorm(n, 0, 1),
                 B1 = rnorm(n, 0, 1),
                 B2 = rnorm(n, 0, 1))

mb <- microbenchmark(
  m1 = df %>% mutate(A = (A1 + A2 + A3)/3),
  m2 = df %>% mutate(A = rowMeans(select(., A1:A3))),
  m3 = df %>% mutate(A = reduce(.[, grepl("^A", names(.))], `+`) / ncol(.[, grepl("^A", names(.))])),
  m4 = rowMeans(df[, grep("^A", names(df))]),
  m5 = df[, grep("^A", names(df))] %>% rowMeans()
)

mb

autoplot(mb)

纯R的方法最快,其次是基于R的子集/dplyr管道。


不错的基准测试! 对性能影响不大,但需要注意的是对于相同的输出 %>% cbind(df, A = .) (或类似的) 需要添加到 m4m5 - arg0naut91
1
@arg0naut 或者 %>% bind_cols(df, A = .),使用 dplyr 函数。 - Rui Barradas

2
在我之前的版本中,我认为rowMeans是瓶颈所在,但实际上减慢计算速度的是使用select - 最好还是坚持使用grep族:
最初的回答:
先前我以为问题出在rowMeans,但实际上影响计算速度的是使用了select,因此最好还是使用grep系列函数。
df %>% mutate(A = rowMeans(.[, grepl("^A", names(.))]))

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