簡體   English   中英

R dplyr 的 group_by 也考慮空組

[英]R dplyr's group_by consider empty groups as well

讓我們考慮以下數據框:

set.seed(123)
data <- data.frame(col1 = factor(rep(c("A", "B", "C"), 4)),
                   col2 = factor(c(rep(c("A", "B", "C"), 3), c("A", "A", "A"))),
                   val1 = 1:12,
                   val2 = rnorm(12, 10, 15))

應急表如下:

cont_tab <- table(data$col1, data$col2, dnn = c("col1", "col2"))

cont_tab

    col2
col1 A B C
   A 4 0 0
   B 1 3 0
   C 1 0 3

如您所見,有些對沒有出現:(A,B)、(A,C)、(B,C)、(C,B)。 我分析的最終目標是列出所有對(在本例中為 9)並顯示每個對的統計數據。 在使用dplyr::group_by()函數時,我遇到了一個限制。 即, dplyr::group_by()僅考慮現有對(至少出現一次的對):

data %>%
  group_by(col1, col2) %>%
  summarize(stat = sum(val2) - sum(val1))

# A tibble: 5 x 3
# Groups:   col1 [?]
  col1  col2   stat
  <fct> <fct> <dbl>
1 A     A      58.1
2 B     A     -16.4
3 B     B      17.0
4 C     A     -12.9
5 C     C     -41.9

我想到的輸出有 9 行(其中 4 行的stat等於 0)。 dplyr可行嗎?

編輯:抱歉一開始太含糊。 真正的問題比計算特定對出現的次數更復雜。 我添加了新數據,以使真正的問題更加明顯。

tidyr添加spread以獲得與table相同的結果要容易得多

library(dplyr)
library(tidyr)
count(data, col1, col2) %>% 
      spread(col2, n, fill = 0)
# A tibble: 3 x 4
# Groups:   col1 [3]
#  col1      A     B     C
#  <fct> <dbl> <dbl> <dbl>
#1 A         4     0     0
#2 B         1     3     0
#3 C         1     0     3

注意: group_by/summarise步驟在這里更改為count

正如@divibisan 所建議的,如果 OP 需要長格式,則在最后添加gather

data %>%
   group_by(col1, col2) %>%
   summarize(stat = n()) %>%
   spread(col2, stat, fill = 0) %>%
   gather(col2, stat, A:C)
# A tibble: 9 x 3
# Groups:   col1 [3]
#  col1  col2   stat
#  <fct> <chr> <dbl>
#1 A     A         4
#2 B     A         1
#3 C     A         1
#4 A     B         0
#5 B     B         3
#6 C     B         0
#7 A     C         0
#8 B     C         0
#9 C     C         3

更新

使用 OP 帖子中的更新數據

data %>%
   group_by(col1, col2) %>%
   summarize(stat = sum(val2) - sum(val1)) %>% 
   spread(col2, stat, fill = 0)  %>% 
   gather(col2, stat, -1)
# A tibble: 9 x 3
# Groups:   col1 [3]
#  col1  col2    stat
#  <fct> <chr>  <dbl>
#1 A     A       7.76
#2 B     A     -20.8 
#3 C     A       6.97
#4 A     B       0   
#5 B     B      28.8 
#6 C     B       0   
#7 A     C       0   
#8 B     C       0   
#9 C     C       9.56

即使沒有dplyr這也是可行的

as.data.frame(table(data$col1, data$col2, dnn = c("col1", "col2")))
#  col1 col2 Freq
#1    A    A    4
#2    B    A    1
#3    C    A    1
#4    A    B    0
#5    B    B    3
#6    C    B    0
#7    A    C    0
#8    B    C    0
#9    C    C    3

您可以使用tidyr::complete

library(tidyverse)

data %>%
  group_by(col1, col2) %>%
  summarize(stat = n()) %>% 
  # additions below
  ungroup %>% 
  complete(col1, col2, fill = list(stat = 0))

# # A tibble: 9 x 3
#   col1  col2   stat
#   <chr> <chr> <dbl>
# 1 A     A         4
# 2 A     B         0
# 3 A     C         0
# 4 B     A         1
# 5 B     B         3
# 6 B     C         0
# 7 C     A         1
# 8 C     B         0
# 9 C     C         3

您還可以對第一部分使用count 下面的代碼給出與上面的代碼相同的輸出

data %>%
  count(col1, col2) %>%
  complete(col1, col2, fill = list(n = 0)) 

還有一個使用tidyr::complete()tidyverse可能性:

data %>% 
 group_by_all() %>%
 add_count() %>%
 complete(col1, col2, fill = list(n = 0)) %>%
 distinct()

  col1  col2      n
  <fct> <fct> <dbl>
1 A     A         4
2 A     B         0
3 A     C         0
4 B     A         1
5 B     B         3
6 B     C         0
7 C     A         1
8 C     B         0
9 C     C         3

或者使用tidyr::expand()

data %>% 
 count(col1, col2) %>%
 right_join(data %>%
            expand(col1, col2), by = c("col1" = "col1",
                                       "col2" = "col2")) %>%
 replace_na(list(n = 0))

或者使用tidyr::crossing()

data %>%
 count(col1, col2) %>%
 right_join(crossing(col1 = unique(data$col1), 
                     col2 = unique(data$col2)), by = c("col1" = "col1",
                                                       "col2" = "col2")) %>%
 replace_na(list(n = 0))

這里有一些解決方法,我希望它對你有用。 將您的表格與所有組合的表格合並,並用 0 替換 NA。

data %>%
group_by(col1, col2) %>%
summarize(stat = n()) %>% 
merge(unique(expand.grid(data)), by=c("col1","col2"), all=T) %>% 
replace_na(list(stat=0))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM