在tidyr/dplyr中添加零计数行的正确习惯用法

pet*_*ete 33 r dplyr tidyr

假设我有一些看起来像这样的计数数据:

library(tidyr)
library(dplyr)

X.raw <- data.frame(
    x = as.factor(c("A", "A", "A", "B", "B", "B")),
    y = as.factor(c("i", "ii", "ii", "i", "i", "i")),
    z = 1:6)
X.raw
#   x  y z
# 1 A  i 1
# 2 A ii 2
# 3 A ii 3
# 4 B  i 4
# 5 B  i 5
# 6 B  i 6
Run Code Online (Sandbox Code Playgroud)

我想像这样整理和总结:

X.tidy <- X.raw %>% group_by(x,y) %>% summarise(count=sum(z))
X.tidy
# Source: local data frame [3 x 3]
# Groups: x
#
#   x  y count
# 1 A  i     1
# 2 A ii     5
# 3 B  i    15
Run Code Online (Sandbox Code Playgroud)

我知道,x=="B"y=="ii"我们所观察到的零计数,而不是缺失值.即实地工作人员实际上在那里,但因为没有正数,所以没有输入原始数据的行.我可以通过这样做明确地添加零计数:

X.fill <- X.tidy %>% spread(y, count, fill=0) %>% gather(y, count, -x)
X.fill
# Source: local data frame [4 x 3]
# 
#   x  y count
# 1 A  i     1
# 2 B  i    15
# 3 A ii     5
# 4 B ii     0
Run Code Online (Sandbox Code Playgroud)

但这似乎是一种迂回做事的方式.他们是一个更清洁的成语吗?

只是为了澄清:我的代码已经做什么,我需要做的,用spread那么gather,还等什么我感兴趣的是找到一个更直接的路线 tidyrdplyr.

aos*_*ith 24

tidyrcomplete功能就是针对这种情况.

来自文档:

这是expand(),left_join()和replace_na的包装,它对于完成缺少的数据组合很有用.

你可以用两种方式使用它.首先,你可以总结,"完成"的用的所有组合数据集之前使用它的原始数据集xy,并填充z为0(你可以使用默认的NA fill和使用na.rm = TRUEsum).

X.raw %>% 
    complete(x, y, fill = list(z = 0)) %>% 
    group_by(x,y) %>% 
    summarise(count = sum(z))

Source: local data frame [4 x 3]
Groups: x [?]

       x      y count
  <fctr> <fctr> <dbl>
1      A      i     1
2      A     ii     5
3      B      i    15
4      B     ii     0
Run Code Online (Sandbox Code Playgroud)

您还可以complete在预先汇总的数据集上使用.请注意complete尊重分组. X.tidy已分组,因此您可以ungroup通过x和/ y或仅列出要在每个组中完成的变量来完成数据集- 在本例中,y.

# Complete after ungrouping
X.tidy %>% 
    ungroup %>%
    complete(x, y, fill = list(count = 0))

# Complete within grouping
X.tidy %>% 
    complete(y, fill = list(count = 0))
Run Code Online (Sandbox Code Playgroud)

每个选项的结果都是相同的:

Source: local data frame [4 x 3]

       x      y count
  <fctr> <fctr> <dbl>
1      A      i     1
2      A     ii     5
3      B      i    15
4      B     ii     0
Run Code Online (Sandbox Code Playgroud)


Moo*_*per 14

由于dplyr 0.8您可以通过在中设置参数.drop = FALSE来实现group_by

X.tidy <- X.raw %>% group_by(x, y, .drop = FALSE) %>% summarise(count=sum(z))
X.tidy
# # A tibble: 4 x 3
# # Groups:   x [2]
#   x     y     count
#   <fct> <fct> <int>
# 1 A     i         1
# 2 A     ii        5
# 3 B     i        15
# 4 B     ii        0
Run Code Online (Sandbox Code Playgroud)

  • 如果您在这里做到了,这对您不起作用,这只是一个提示:请确保您在 group_by() 中使用的是因子而不是字符列 (9认同)