2017-05-26 29 views
2

dplyr 0.5.0中,在分組數據幀上調用summarise並不能保證任何生成的行順序(目前,它按組重新排序行,不知道它如何處理重複的分組級別)。做一個mutate +過濾器vs分組數據幀彙總是否有任何缺點?

爲了解決這個問題,我想用mutate(x = ...) %>% filter(row_number() == 1)替換所有summarise(x = ...)操作。這樣做有什麼缺點或缺點嗎?

這兩個操作的例子。

tmp_df <- 
    data.frame(group = rep(c(2L, 1L), each = 5), b = rep(c(-1, 1), each = 5)) %>% 
    group_by(group) 

tmp_df %>% 
    summarise(b = sum(b)) 

tmp_df %>% 
    mutate(b = sum(b)) %>% 
    filter(row_number() == 1) 

生產:

> tmp_df %>% 
+  summarise(b = sum(b)) 
# A tibble: 2 × 2 
    group  b 
    <int> <dbl> 
1  1  5 
2  2 -5 
> tmp_df %>% 
+  mutate(b = sum(b)) %>% 
+  filter(row_number() == 1) 
Source: local data frame [2 x 2] 
Groups: group [2] 

    group  b 
    <int> <dbl> 
1  2 -5 
2  1  5 

編輯:在迴應評論,爲便於閱讀,我可以定義函數:

summarise_o <- function (.data, ...) { 
    # order preserving summarise 
    mutate_(.data, .dots = lazyeval::lazy_dots(...)) %>% 
     filter(row_number() == 1) %>% 
     return 
} 

,只需撥打:

tmp_df %>% 
    summarise_o(b = sum(b)) 
+0

'summarize()'對我來說似乎更具可讀性/有意義,因爲這就是您正在做的事情。如果行順序如此重要,請在後排序。 – Marius

+0

我願意犧牲可讀性來保留行排序,因爲分析管道我可能已經忘記了我如何訂購我的數據框。 (實際上我真正喜歡的是定義一個替代mutate +過濾器的新的彙總函數)。 – Alex

+1

使用data.table:'tmp_df%>%data.table%>%group_by(group)%>%summarize(b = sum(b))'顯示我的預期訂單。我加載data.table包而不是dtplyr,但我想它的工作原理是一樣的。 (我使用'data.table()'而不是'setDT()',因爲它更符合dplyr的無法修改的理念。) – Frank

回答

2

一種選擇是創建「組」作爲factor

tmp_df <- data.frame(group = rep(c(2L, 1L), each = 5), b = rep(c(-1, 1), each = 5)) %>% 
      group_by(group = factor(group, levels = unique(group))) 

tmp_df %>% 
    summarise(b = sum(b)) 
# A tibble: 2 x 2 
# group  b 
# <fctr> <dbl> 
#1  2 -5 
#2  1  5 
+0

這是非常整潔,但在正常使用情況下,可能有多個分組變量,但我想你可以創建一個組索引什麼的。 – Alex

+2

@Alex如果有多個組,那麼'df1%>%mutate_at(vars(colsofinterest),funs(因子(。,levels = unique(。))))%>%group_by _(。dots = colsofinterest)' – akrun