eip*_*i10 93 r plyr dplyr tidyr
当使用summarise具有plyr的ddply功能,空类别默认情况下删除.您可以通过添加更改此行为.drop = FALSE.然而,当使用这不起作用summarise用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
Run Code Online (Sandbox Code Playgroud)
不完全是我所希望的.有没有dplyr达到同样的结果的方法.drop=FALSE的plyr?
A5C*_*2T1 59
问题仍然存在,但与此同时,特别是因为您的数据已被考虑因素,您可以使用complete"tidyr"获取您可能正在寻找的内容:
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
Run Code Online (Sandbox Code Playgroud)
如果您希望替换值为零,则需要使用以下内容指定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
Run Code Online (Sandbox Code Playgroud)
npj*_*pjc 20
首先制作分组df
by_b <- tbl_df(df) %>% group_by(b)
Run Code Online (Sandbox Code Playgroud)
然后我们总结通过计数发生的那些水平 n()
res <- by_b %>% summarise( count_a = n() )
Run Code Online (Sandbox Code Playgroud)
然后我们将结果合并到一个包含所有因子水平的数据框中:
expanded_res <- left_join(expand.grid(b = levels(df$b)),res)
Run Code Online (Sandbox Code Playgroud)
最后,在这种情况下,因为我们正在查看计NA数值,所以将值更改为0.
final_counts <- expanded_res[is.na(expanded_res)] <- 0
Run Code Online (Sandbox Code Playgroud)
这也可以在功能上实现,请参阅答案: 使用dplyr向分组数据添加行?
为了感兴趣,我想我会在这种情况下发布一个可怕的黑客.我严重怀疑你是否应该真正做到这一点,但它表明如何group_by()产生atrributes好像df$b是一个字符向量而不是一个水平因素.此外,我并没有假装正确地理解这一点 - 但我希望这有助于我学习 - 这是我发布它的唯一原因!
by_b <- tbl_df(df) %>% group_by(b)
Run Code Online (Sandbox Code Playgroud)
定义数据集中不存在的"越界"值.
oob_val <- nrow(by_b)+1
Run Code Online (Sandbox Code Playgroud)
将属性修改为"技巧" summarise():
attr(by_b, "indices")[[3]] <- rep(NA,oob_val)
attr(by_b, "group_sizes")[3] <- 0
attr(by_b, "labels")[3,] <- 3
Run Code Online (Sandbox Code Playgroud)
做总结:
res <- by_b %>% summarise(count_a = n())
Run Code Online (Sandbox Code Playgroud)
索引并替换所有出现的oob_val
res[res == oob_val] <- 0
Run Code Online (Sandbox Code Playgroud)
给出了预期的:
> res
Source: local data frame [3 x 2]
b count_a
1 1 6
2 2 6
3 3 0
Run Code Online (Sandbox Code Playgroud)
Moo*_*per 16
由于dplyr 0.8 group_by获得了.drop满足您要求的参数:
df = data.frame(a=rep(1:3,4), b=rep(1:2,6))
df$b = factor(df$b, levels=1:3)
df %>%
group_by(b, .drop=FALSE) %>%
summarise(count_a=length(a))
#> # A tibble: 3 x 2
#> b count_a
#> <fct> <int>
#> 1 1 6
#> 2 2 6
#> 3 3 0
Run Code Online (Sandbox Code Playgroud)
@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)
Run Code Online (Sandbox Code Playgroud)
tal*_*lat 11
这不完全是问题中的问题,但至少对于这个简单的例子,您可以使用xtabs获得相同的结果,例如:
使用dplyr:
df %>%
xtabs(formula = ~ b) %>%
as.data.frame()
Run Code Online (Sandbox Code Playgroud)
或更短:
as.data.frame(xtabs( ~ b, df))
Run Code Online (Sandbox Code Playgroud)
结果(两种情况都相同):
b Freq
1 1 6
2 2 6
3 3 0
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
25415 次 |
| 最近记录: |