2017-02-14 93 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

相關問題