dplyr摘要:相当于;。drop=FALSE";在输出中保留长度为零的组的步骤

dplyr摘要:相当于;。drop=FALSE";在输出中保留长度为零的组的步骤,r,dplyr,plyr,tidyr,R,Dplyr,Plyr,Tidyr,当使用summary和plyr的ddply功能时,默认情况下会删除空类别。您可以通过添加.drop=FALSE来更改此行为。但是,当使用summary和dplyr时,这不起作用。有没有其他方法可以在结果中保留空类别 这里有一个假数据的例子 library(dplyr) df = data.frame(a=rep(1:3,4), b=rep(1:2,6)) # Now add an extra level to df$b that has no corresponding value in d

当使用
summary
plyr
ddply
功能时,默认情况下会删除空类别。您可以通过添加
.drop=FALSE
来更改此行为。但是,当使用
summary
dplyr
时,这不起作用。有没有其他方法可以在结果中保留空类别

这里有一个假数据的例子

library(dplyr)

df = data.frame(a=rep(1:3,4), b=rep(1:2,6))

# Now add an extra level to df$b that has no corresponding value in df$a
df$b = factor(df$b, levels=1:3)

# Summarise with plyr, keeping categories with a count of zero
plyr::ddply(df, "b", summarise, count_a=length(a), .drop=FALSE)

  b    count_a
1 1    6
2 2    6
3 3    0

# Now try it with dplyr
df %.%
  group_by(b) %.%
  summarise(count_a=length(a), .drop=FALSE)

  b     count_a .drop
1 1     6       FALSE
2 2     6       FALSE

不完全是我所希望的。在
plyr
中是否有
dplyr
方法可以获得与
.drop=FALSE
相同的结果?

这并不是问题中所问的问题,但至少对于这个简单的示例,您可以使用xtabs获得相同的结果,例如:

使用dplyr:

df %>%
  xtabs(formula = ~ b) %>%
  as.data.frame()
或更短:

as.data.frame(xtabs( ~ b, df))
结果(两种情况下相同):

dplyr解决方案: 先做分组测向

by_b <- tbl_df(df) %>% group_by(b)
然后,我们将结果合并到包含所有因子水平的数据框中:

expanded_res <- left_join(expand.grid(b = levels(df$b)),res)
这也可以在功能上实现,请参见答案:

黑客: 我想出于兴趣,我会发布一个在这种情况下有效的糟糕的黑客。我很怀疑你是否真的应该这样做,但它显示了
groupby()
如何生成一个属性,就好像
df$b
是一个字符向量而不是一个具有级别的因子一样。另外,我并不假装完全理解这一点——但我希望这能帮助我学习——这是我发布它的唯一原因

by_b <- tbl_df(df) %>% group_by(b)
做总结:

res <- by_b %>% summarise(count_a = n())

问题仍然存在,但在此期间,特别是由于您的数据已经分解,您可以使用“tidyr”中的
complete
来获取您可能需要的信息:

library(tidyr)
df %>%
  group_by(b) %>%
  summarise(count_a=length(a)) %>%
  complete(b)
# Source: local data frame [3 x 2]
# 
#        b count_a
#   (fctr)   (int)
# 1      1       6
# 2      2       6
# 3      3      NA
如果希望替换值为零,则需要使用
fill

df %>%
  group_by(b) %>%
  summarise(count_a=length(a)) %>%
  complete(b, fill = list(count_a = 0))
# Source: local data frame [3 x 2]
# 
#        b count_a
#   (fctr)   (dbl)
# 1      1       6
# 2      2       6
# 3      3       0
由于dplyr 0.8
groupby
获得了
。drop
参数,该参数正好满足您的要求:

df=data.frame(a=rep(1:3,4),b=rep(1:2,6))
df$b=系数(df$b,等级=1:3)
df%>%
分组依据(b,.drop=FALSE)%>%
总结(计数a=长度(a))
#>#tibble:3 x 2
#>b计数a
#>      
#> 1 1           6
#> 2 2           6
#> 3 3           0
@Moody_Mudskipper的答案还有一个附加说明:当一个或多个分组变量未编码为因子时,使用
.drop=FALSE
可能会产生潜在的意外结果。见以下示例:

library(dplyr)
data(iris)

# Add an additional level to Species
iris$Species = factor(iris$Species, levels=c(levels(iris$Species), "empty_level"))

# Species is a factor and empty groups are included in the output
iris %>% group_by(Species, .drop=FALSE) %>% tally

#>   Species         n
#> 1 setosa         50
#> 2 versicolor     50
#> 3 virginica      50
#> 4 empty_level     0

# Add character column
iris$group2 = c(rep(c("A","B"), 50), rep(c("B","C"), each=25))

# Empty groups involving combinations of Species and group2 are not included in output
iris %>% group_by(Species, group2, .drop=FALSE) %>% tally

#>   Species     group2     n
#> 1 setosa      A         25
#> 2 setosa      B         25
#> 3 versicolor  A         25
#> 4 versicolor  B         25
#> 5 virginica   B         25
#> 6 virginica   C         25
#> 7 empty_level <NA>       0

# Turn group2 into a factor
iris$group2 = factor(iris$group2)

# Now all possible combinations of Species and group2 are included in the output, 
#  whether present in the data or not
iris %>% group_by(Species, group2, .drop=FALSE) %>% tally

#>    Species     group2     n
#>  1 setosa      A         25
#>  2 setosa      B         25
#>  3 setosa      C          0
#>  4 versicolor  A         25
#>  5 versicolor  B         25
#>  6 versicolor  C          0
#>  7 virginica   A          0
#>  8 virginica   B         25
#>  9 virginica   C         25
#> 10 empty_level A          0
#> 11 empty_level B          0
#> 12 empty_level C          0

Created on 2019-03-13 by the reprex package (v0.2.1)
库(dplyr)
数据(iris)
#为物种添加一个附加级别
iris$物种=因子(iris$物种,等级=c(等级(iris$物种),“空等级”))
#物种是一个因素,空组包含在输出中
iris%%>%分组依据(物种,.drop=FALSE)%%>%计数
#>物种n
#>1刚毛50
#>2彩色50
#>3弗吉尼亚州50
#>4空_级别0
#添加字符列
iris$group2=c(代表(c(“A”、“B”),50),代表(c(“B”、“c”),各=25))
#涉及物种和组2组合的空组不包括在输出中
虹膜%>%分组依据(物种,分组2,.drop=FALSE)%>%计数
#>种群2 n
#>1刚毛A 25
#>2 setosa B 25
#>3彩色A 25
#>4彩色B25
#>5维吉尼亚B 25
#>6维吉尼亚C 25
#>7空_级别0
#把第二组变成一个因素
iris$group2=系数(iris$group2)
#现在,所有可能的物种和第2组的组合都包含在输出中,
#是否存在于数据中
虹膜%>%分组依据(物种,分组2,.drop=FALSE)%>%计数
#>种群2 n
#>1刚毛A 25
#>2 setosa B 25
#>3刚毛C 0
#>4彩色A 25
#>5彩色B25
#>6彩色C 0
#>7弗吉尼亚A 0
#>8维吉尼亚B 25
#>9弗吉尼亚C 25
#>10空_A级0
#>11空_B级0
#>12空_等级C 0
由reprex软件包(v0.2.1)于2019年3月13日创建

我花了很多时间才弄明白这一点,所以我将在这里提及。。。如果按2个变量分组,并且它们是字符而不是因子,则在完成之前需要使用
ungroup()
。如果您注意到
complete
没有实际完成,则可能需要
ungroup
。如果您有更多分组变量呢?如果我使用组中的所有分组变量,我会得到大量的行(比我原来的数据帧多得多)。我想:你必须使用嵌套:-),所以把所有不应该在它们之间组合的变量放入
complete(variablewithdroppedlevels,nesting(var1,var2,var3))
(实际上是在帮助中完成的。我还是花了一段时间才弄明白我在你的答案中添加了一个额外的注释。如果你不喜欢编辑,请随意删除。我已经在github上找到了这是一个bug还是预期的行为。@eipi10稍微短一点是使用
计数。
虹膜%>%count(物种,第2组,.drop=FALSE)
attr(by_b, "indices")[[3]] <- rep(NA,oob_val)
attr(by_b, "group_sizes")[3] <- 0
attr(by_b, "labels")[3,] <- 3
res <- by_b %>% summarise(count_a = n())
res[res == oob_val] <- 0
> res
Source: local data frame [3 x 2]

b count_a
1 1       6
2 2       6
3 3       0
library(tidyr)
df %>%
  group_by(b) %>%
  summarise(count_a=length(a)) %>%
  complete(b)
# Source: local data frame [3 x 2]
# 
#        b count_a
#   (fctr)   (int)
# 1      1       6
# 2      2       6
# 3      3      NA
df %>%
  group_by(b) %>%
  summarise(count_a=length(a)) %>%
  complete(b, fill = list(count_a = 0))
# Source: local data frame [3 x 2]
# 
#        b count_a
#   (fctr)   (dbl)
# 1      1       6
# 2      2       6
# 3      3       0
library(dplyr)
data(iris)

# Add an additional level to Species
iris$Species = factor(iris$Species, levels=c(levels(iris$Species), "empty_level"))

# Species is a factor and empty groups are included in the output
iris %>% group_by(Species, .drop=FALSE) %>% tally

#>   Species         n
#> 1 setosa         50
#> 2 versicolor     50
#> 3 virginica      50
#> 4 empty_level     0

# Add character column
iris$group2 = c(rep(c("A","B"), 50), rep(c("B","C"), each=25))

# Empty groups involving combinations of Species and group2 are not included in output
iris %>% group_by(Species, group2, .drop=FALSE) %>% tally

#>   Species     group2     n
#> 1 setosa      A         25
#> 2 setosa      B         25
#> 3 versicolor  A         25
#> 4 versicolor  B         25
#> 5 virginica   B         25
#> 6 virginica   C         25
#> 7 empty_level <NA>       0

# Turn group2 into a factor
iris$group2 = factor(iris$group2)

# Now all possible combinations of Species and group2 are included in the output, 
#  whether present in the data or not
iris %>% group_by(Species, group2, .drop=FALSE) %>% tally

#>    Species     group2     n
#>  1 setosa      A         25
#>  2 setosa      B         25
#>  3 setosa      C          0
#>  4 versicolor  A         25
#>  5 versicolor  B         25
#>  6 versicolor  C          0
#>  7 virginica   A          0
#>  8 virginica   B         25
#>  9 virginica   C         25
#> 10 empty_level A          0
#> 11 empty_level B          0
#> 12 empty_level C          0

Created on 2019-03-13 by the reprex package (v0.2.1)