dplyr::summarize()
函数可以对数据应用任意函数,但似乎函数必须返回标量值 . 我很好奇是否有一种合理的方法来处理返回向量值的函数而不需要多次调用该函数 .
这是一个有点愚蠢的最小例子 . 考虑一个提供多个值的函数,例如:
f <- function(x,y){
coef(lm(x ~ y, data.frame(x=x,y=y)))
}
和看起来像这样的数据:
df <- data.frame(group=c('A','A','A','A','B','B','B','B','C','C','C','C'), x=rnorm(12,1,1), y=rnorm(12,1,1))
我想做的事情如下:
df %>%
group_by(group) %>%
summarise(f(x,y))
并返回一个表,该表为每个返回值添加了2列,而不是通常的1列 . 相反,这个错误: Expecting single value
当然,我们可以通过多次给出函数参数从 dlpyr::summarise()
获取多个值:
f1 <- function(x,y) coef(lm(x ~ y, data.frame(x=x,y=y)))[[1]]
f2 <- function(x,y) coef(lm(x ~ y, data.frame(x=x,y=y)))[[2]]
df %>%
group_by(group) %>%
summarise(a = f1(x,y), b = f2(x,y))
这给出了所需的输出:
group a b
1 A 1.7957245 -0.339992915
2 B 0.5283379 -0.004325209
3 C 1.0797647 -0.074393457
但这样的编码是荒谬粗暴和丑陋的 .
data.table
更简洁地处理这个案子:
dt <- as.data.table(df)
dt[, f(x,y), by="group"]
但创建一个输出,使用额外的行而不是其他列来扩展表,从而导致输出既困惑又难以使用:
group V1
1: A 1.795724536
2: A -0.339992915
3: B 0.528337890
4: B -0.004325209
5: C 1.079764710
6: C -0.074393457
当然,我们可以在这里使用更多经典的 apply
策略,
sapply(levels(df$group), function(x) coef(lm(x~y, df[df$group == x, ])))
A B C
(Intercept) 1.7957245 0.528337890 1.07976471
y -0.3399929 -0.004325209 -0.07439346
但这牺牲了优雅,我怀疑分组的速度 . 特别要注意的是,在这种情况下我们不能使用我们的预定义函数 f
,但必须将分组硬编码到函数定义中 .
是否有 dplyr
函数来处理这种情况?如果没有,是否有一种更优雅的方法来处理这一过程,即按组分析数据帧中的向量值函数?
2 回答
你可以试试
do
基于
f1
和f2
的输出是更新
如果您使用
data.table
,则获得类似结果的选项是这就是为什么我仍然喜欢
plyr::ddply()
: