为什么dplyr :: summarize不能使用我的自定义函数?

时间:2017-02-14 17:19:38

标签: r dplyr

我想在dplyr的函数summarise()中使用自定义函数,如下所示:

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)

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

1 个答案:

答案 0 :(得分:4)

summarize依次评估每个表达式,所以当你的第一行

x = mean(x)

x列(每个组内)由单个值mean(x)替换。您的下一行会在该常量sd上调用x,而单个值的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允许您引用刚刚创建的列。