2017-02-14 129 views
2

我想dplyr的功能summarise()中使用自定义函数,如下所示:为什么dplyr :: summarize不能使用我的自定义函数?

library(dplyr) 

# Define custom function for calculating standard error 
se <- function(x) sd(x)/sqrt(length(x)) 

# Create a dummy data table with two groups 
d <- tibble(gp = sample(c("A", "B"), 20, replace = T), 
      x = ifelse(gp == "A", rnorm(20), rnorm(20) + 1)) 

# Summarise data 
d %>% 
    group_by(gp) %>% 
    summarise(x = mean(x), 
      se = se(x)) 

为什么我得到NA的输出,而不是标准错误的正确值的值?

# A tibble: 2 × 3 
    gp   x se 
    <chr>  <dbl> <lgl> 
1  A -0.4060173 NA 
2  B 0.2999004 NA 

我知道一些可能的选择。例如,使用基本包:

tapply(d$x, d$gp, se) 

但我不明白为什么第一个版本给出了它的结果。

+2

这是dplyr选择评估事物的“自然”后果。而不是前面的'x = mean(x)',试试'x1 = mean(x)'。 – joran

+0

......想一想的一种方法是,当它达到'se = se(x)'时,dplyr必须决定“什么是x”的答案?对这个问题有几个“显而易见”的答案,但是它选择的是刚刚重新定义的版本,现在版本长度为1,所以没有标准偏差。 – joran

+2

我不认为你不使用'se'函数的版本是合理的。因为即使这样,它也会明白'x'只有一个值,没有std dev。你能再检查一次吗? – AntoniosK

回答

4

summarize评估反过来每个表达式,因此,当您的第一行不

x = mean(x) 

x柱(每个组内)是由一个单一的值,mean(x)替换。您的下一行在该常数x上调用sd,单个值的sdNA

正如@joran在评论中所说的,如果您只是为您的平均值列选择不同的名称,那么一切都将起作用。

d %>% 
    group_by(gp) %>% 
    summarise(avg = mean(x), 
      se = se(x)) 
# # A tibble: 2 × 3 
#  gp  avg  se 
# <chr>  <dbl>  <dbl> 
# 1  A -0.2879016 0.2264810 
# 2  B 0.8804859 0.2625018 

注意,这种顺序评价是dplyr一个考虑周全的功能。 dplyr::mutatebase::transform之间的实际区别正是如此。

dd = data.frame(x = 1:3) 
base::transform(dd, x = 0, y = x * 2) 
# x y 
# 1 0 2 
# 2 0 4 
# 3 0 6 

dplyr::mutate(dd, x = 0, y = x * 2) 
# x y 
# 1 0 0 
# 2 0 0 
# 3 0 0 

这在Introduction to dplyr vignette叫了一声:

dplyr::mutate()以同样的方式为plyr::mutate()和类似base::transform()mutate()transform()之间的主要区别在于mutate允许您引用刚刚创建的列。

+0

谢谢!现在感觉很蠢,因为没有意识到... – user2390246

相关问题