2016-08-30 106 views
21

看來summarisesummarise_each正在對它們提供的回調函數進行不必要的額外調用。假設我們有以下dplyr summarize()和summarise_each()對所提供的函數進行額外調用

X <- data.frame(Group = rep(c("G1","G2"),2:3), Var1 = 1:5, Var2 = 11:15) 

,看起來像這樣:

Group Var1 Var2 
1 G1 1 11 
2 G1 2 12 
3 G2 3 13 
4 G2 4 14 
5 G2 5 15 

進一步假設我們有一個(潛在的昂貴)功能

f <- function(v) 
{ 
    cat("Calling f with vector", v, "\n") 
    ## ...additional bookkeeping and processing... 
    mean(v) 
} 

,我們想申請每個組中的每個變量。使用dplyr,我們不妨去了解它以下列方式:

X %>% group_by(Group) %>% summarise_each(funs(f)) 

但是,輸出顯示f被稱爲一個額外的時間爲每個變量在G1:

Calling f with vector 1 2 
Calling f with vector 1 2 
Calling f with vector 3 4 5 
Calling f with vector 11 12 
Calling f with vector 11 12 
Calling f with vector 13 14 15 
# A tibble: 2 x 3 
    Group Var1 Var2 
    <fctr> <dbl> <dbl> 
1  G1 1.5 11.5 
2  G2 4.0 14.0 

同樣的問題存在使用summarize時:

> X %>% group_by(Group) %>% summarise(test = f(Var1)) 
Calling f with vector 1 2 
Calling f with vector 1 2 
Calling f with vector 3 4 5 
# A tibble: 2 × 2 
    Group test 
    <fctr> <dbl> 
1  G1 1.5 
2  G2 4.0 

這究竟是爲什麼,以及如何將一個去阻止summarisesummarise_each從打這些額外的電話?

(這是使用R版本3.3.0和0.5.0版本dplyr

編輯:看來,問題與group_bysummarise/summarise_each之間的相互作用有關。沒有分組,不會有額外的呼叫。此外,mutatemutate_each不會遇到此問題。 (對於這些發現,信用度:eddieipi10

+1

你可以進一步縮小範圍 - 問題出在'summarise'(和'group_by') – eddi

+0

我實際上傾向於使用'group_by'的問題。做一個簡單的'X%>%彙總(test = f(Var1))'表現得像預期的那樣,但是'X%>%group_by(Group)%>%summarize(test = f(Var1))'不。 –

+1

'mutate'和'mutate_each'不會受到這個錯誤的影響(與'group_by'一起使用時) – eddi

回答

4

儘管dplyr 0.5.0(2016年6月24日發佈)中仍存在此問題,但它已在dplyr GitHub repro中修復。它在2016-09-24制定了this commit。我已經確認,當我在前一次提交中籤出並構建版本時,我可以重現該問題,但不能在從其中一個或更多版本進行構建時複製該問題。

(是的,我嘗試了一大堆其他的之前,我發現了它。爲什麼我去這樣的長度賺取虛上網點的希望,我離開爲我的治療師的問題。:)

特別是,在inst/include/dplyr/Result/CallbackProcessor.h功能SEXP process_data(const Data& gdf),注意這些變化:

CLASS* obj = static_cast<CLASS*>(this); 
    typename Data::group_iterator git = gdf.group_begin(); 

    RObject first_result = obj->process_chunk(*git); 
    ++git; // This line was added 

for (int i = 1; i < ngroups; ++git, ++i) { // changed from starting at i = 0 
    RObject chunk = obj->process_chunk(*git); 

[評論由我添加的,沒有t部分實際來源]

+0

偉大的偵探工作! –

相關問題