R:当不是所有类别都出现时,统计每列中的类别

R: Count categories in each column when not all categories appear

具有 character 列的简单 data.frame

df <- data.frame(x = c("a", "b", "c", "c"), y = c("a", "b", "b", "c"))

假设我想计算每一列的类别,并快速返回另一个 data.frame。以下使用 purrr 中的 map 是优雅且有效的:

df %>%
  map(table) %>%
  Reduce(cbind, .) %>%
  data.frame() %>%
  set_names(c("x", "y"))

  x y
a 1 1
b 1 2
c 2 1

然而。当不是所有类别都出现在每一列中时怎么办?示例:

df2 <- data.frame(x = c("a", "b", "b"), y = c("a", "a", "a"))

我希望 y 列中 b 的计数为 0。但我得到:

df2 %>%
  map(table) %>%
  Reduce(cbind, .) %>%
  data.frame() %>%
  set_names(c("x", "y"))

  x y
a 1 3
b 2 3

没有任何警告!我猜这是因为 cbind 习惯回收一列的元素以匹配另一列的长度。我尝试使用 qpcR:::cbind.na 至少获得缺失类别的 NA 值,稍后我可以将其转换为 0 但我收到此错误:

Error in matrix(, maxRow - nrow(x), ncol(x)) : 
  invalid 'ncol' value (too large or NA)

什么是好的、快速的解决方案,最好来自 tidyverse 软件包集?

更新:

对于我们知道所有类别都在所有列中的第一种情况:

df %>% dmap(function(x) as.numeric(table(x)))

可能更优雅。

您可以使用 tidyr 的 gather()spread(),中间使用 dplyr 的 count()

library(dplyr)
library(tidyr)

df2 <- data_frame(x = c("a", "b", "b"), y = c("a", "a", "a"))

df2 %>%
  gather(key, value) %>%
  count(key, value) %>%
  spread(key, n, fill = 0)

结果:

  value     x     y
* <chr> <dbl> <dbl>
1     a     1     3
2     b     2     0

spread() 中的 fill = 0 是导致 b/y 对为 0 的原因。