R ave by columns

TMS*_*TMS 4 r dataframe

我想ave在数据框上的许多列(数十)上使用该函数:

ave(df[,the_cols], df[,c('site', 'month')], FUN = mean)
Run Code Online (Sandbox Code Playgroud)

问题是在所有列上一起ave运行该mean函数the_cols.有没有办法the_cols分别为每个列运行它?

我试着看看其他功能.tapply并且aggregate不同,它们每组只返回一行.我需要ave行为,即返回原始行中给出的相同行数df.还有一个by函数,但使用它会非常笨拙,因为它返回一个复杂的列表结构,必须以某种方式进行转换.

当然存在许多笨拙和丑陋(通过&do.call,多个*应用函数调用等)解决方案但是有一些非常简单和优雅吗?

Rei*_*son 5

也许我错过了一些东西,但apply()这里的方法可以很好地工作,也不会丑陋或需要任何丑陋的黑客.一些虚拟数据:

df <- data.frame(A = rnorm(20), B = rnorm(20), site = gl(5,4), month = gl(10, 2))
Run Code Online (Sandbox Code Playgroud)

出什么问题了:

sapply(df[, c("A","B")], ave, df$site, df$month)
Run Code Online (Sandbox Code Playgroud)

data.frame()如果你真的想要那么强制通过数据框.

R> sapply(df[, c("A","B")], ave, df$site, df$month)
            A        B
 [1,]  0.0775  0.04845
 [2,]  0.0775  0.04845
 [3,] -1.5563  0.43443
 [4,] -1.5563  0.43443
 [5,]  0.7193  0.01151
 [6,]  0.7193  0.01151
 [7,] -0.9243 -0.28483
 [8,] -0.9243 -0.28483
 [9,]  0.3316  0.14473
[10,]  0.3316  0.14473
[11,] -0.2539  0.20384
[12,] -0.2539  0.20384
[13,]  0.5558 -0.37239
[14,]  0.5558 -0.37239
[15,]  0.1976 -0.22693
[16,]  0.1976 -0.22693
[17,]  0.2031  1.11041
[18,]  0.2031  1.11041
[19,]  0.3229 -0.53818
[20,]  0.3229 -0.53818
Run Code Online (Sandbox Code Playgroud)

把它放在一起多一点,怎么样

AVE <- function(df, cols, ...) {
  dots <- list(...)
  out <- sapply(df[, cols], ave, ...)
  out <- data.frame(as.data.frame(dots), out)
  names(out) <- c(paste0("Fac", seq_along(dots)), cols)
  out
}

R> AVE(df, c("A","B"), df$site, df$month)
   Fac1 Fac2       A        B
1     1    1  0.0775  0.04845
2     1    1  0.0775  0.04845
3     1    2 -1.5563  0.43443
4     1    2 -1.5563  0.43443
5     2    3  0.7193  0.01151
6     2    3  0.7193  0.01151
7     2    4 -0.9243 -0.28483
8     2    4 -0.9243 -0.28483
9     3    5  0.3316  0.14473
10    3    5  0.3316  0.14473
11    3    6 -0.2539  0.20384
12    3    6 -0.2539  0.20384
13    4    7  0.5558 -0.37239
14    4    7  0.5558 -0.37239
15    4    8  0.1976 -0.22693
16    4    8  0.1976 -0.22693
17    5    9  0.2031  1.11041
18    5    9  0.2031  1.11041
19    5   10  0.3229 -0.53818
20    5   10  0.3229 -0.53818
Run Code Online (Sandbox Code Playgroud)

目前与...我合作的细节让我逃避,但你应该能够为Fac1我在这里使用的等等获得更好的名字.

我会为你抛出一个替代表示:aggregate()但是使用ave()函数而不是mean():

R> aggregate(cbind(A, B) ~ site + month, data = df, ave)
   site month     A.1     A.2      B.1      B.2
1     1     1  0.0775  0.0775  0.04845  0.04845
2     1     2 -1.5563 -1.5563  0.43443  0.43443
3     2     3  0.7193  0.7193  0.01151  0.01151
4     2     4 -0.9243 -0.9243 -0.28483 -0.28483
5     3     5  0.3316  0.3316  0.14473  0.14473
6     3     6 -0.2539 -0.2539  0.20384  0.20384
7     4     7  0.5558  0.5558 -0.37239 -0.37239
8     4     8  0.1976  0.1976 -0.22693 -0.22693
9     5     9  0.2031  0.2031  1.11041  1.11041
10    5    10  0.3229  0.3229 -0.53818 -0.53818
Run Code Online (Sandbox Code Playgroud)

请注意所述的输出,但如果需要,它可以很容易地重塑.