考虑以下互动示例,它生成一个汇总表格:
library(dplyr)
tg <- ToothGrowth
ci_int <- 0.95
tg %>%
group_by(supp, dose) %>%
summarise(N = n(),
mean = mean(len, na.rm = T),
sd = sd(len, na.rm = T),
se = sd / sqrt(N),
ci = se * qt(ci_int / 2 + 0.50, N - 1))
# supp dose N mean sd se ci
# (fctr) (dbl) (int) (dbl) (dbl) (dbl) (dbl)
# 1 OJ 0.5 10 13.23 4.459709 1.4102837 3.190283
# 2 OJ 1.0 10 22.70 3.910953 1.2367520 2.797727
# 3 OJ 2.0 10 26.06 2.655058 0.8396031 1.899314
# 4 VC 0.5 10 7.98 2.746634 0.8685620 1.964824
# 5 VC 1.0 10 16.77 2.515309 0.7954104 1.799343
# 6 VC 2.0 10 26.14 4.797731 1.5171757 3.432090
我想把这个转化成一个函数,将 data.frame
, measure
变量, groupvars
分组变量和 conf.int
抽象出来。有了下面的开端:
library(lazyeval)
summarySE <- function(df, measure, groupvars, conf.int = 0.95) {
summary_dots <- list(
~ n(),
interp(~ mean(var, na.rm = T), var = as.name(measure)),
interp(~ sd(var, na.rm = T), var = as.name(measure))
)
df %>%
group_by_(.dots = groupvars) %>%
summarise_(.dots = setNames(summary_dots, c("N", "mean", "sd")))
}
summarySE(tg, "len", c("supp", "dose"))
这将产生:
# supp dose N mean sd
# (fctr) (dbl) (int) (dbl) (dbl)
# 1 OJ 0.5 10 13.23 4.459709
# 2 OJ 1.0 10 22.70 3.910953
# 3 OJ 2.0 10 26.06 2.655058
# 4 VC 0.5 10 7.98 2.746634
# 5 VC 1.0 10 16.77 2.515309
# 6 VC 2.0 10 26.14 4.797731
然而,这似乎不太DRY?此外,我不确定如何实现se
和ci
,而不会变得过于复杂/冗长?也许有一个更好的方法,或者也许应该将其分成几个函数?
如何将上面的摘要表转换为函数,以便我可以传递任何组合具有不同measure
和groupvars
的data.frame
,并具有dplyr
的“精神”?
supp
和dose
作为向量传递,即c(supp, dose)
-- 我总是害怕使用...
-- 是否有一种快速的替代方法将它们作为group = c(...)
传递? - JasonAizkalnslazy_dots
。然后使用一个列表来作为分组变量,并将其直接提供给group_by_
。但是它们必须被引用。例如:summarySE(tg, len, list(~supp, ~dose))
。无法想象如何将一系列裸名称懒惰地捕获到懒惰对象的列表中。 - Axeman