创建具有按行类别汇总的多个变量的交叉表

Creating Crosstable with Multiple Variables Summarized by Row Categories

我有兴趣按样本类别总结几个结果并将其全部呈现在一个 table 中。输出类似于:

vs am
cyl 0 1 0 1
4 1 10 3 8
6 3 4 4 3
8 14 0 12 2

我是否能够合并(cbind")由以下人员生成的 tables:

ftable(mtcars$cyl, mtcars$vs)

并由:

ftable(mtcars$cyl, mtcars$am)

crosstable() and CrossTable() 包显示了希望,但我看不出如何在不嵌套的情况下将其扩展到多组列。

所示,ftable 可以接近:

ftable(vs + am ~ cyl, mtcars)

除了也在 vs.

中嵌套 am

类似地,dplyr 通过

接近
library(dplyr)
mtcars %>%
  group_by(cyl, vs, am) %>%
  summarize(count = n())

或更复杂的东西,例如

但我有几个变量要呈现,这种嵌套破坏了在我的案例中进行总结的能力。

也许 可以在比我聪明的人手中工作?

蒂娅!

foo = function(df, grp, vars) {
    lapply(vars, function(nm) {
        tmp = as.data.frame(as.matrix(ftable(reformulate(grp, nm), df)))
        names(tmp) = paste0(nm, "_", names(tmp))
        tmp
    })
}

do.call(cbind, foo(mtcars, "cyl", c("vs", "am", "gear")))
#   vs_0 vs_1 am_0 am_1 gear_3 gear_4 gear_5
# 4    1   10    3    8      1      8      2
# 6    3    4    4    3      2      4      1
# 8   14    0   12    2     12      0      2

基于purrr::map_dfctidyr::pivot_wider的解决方案:

library(tidyverse)

map_dfc(c("vs", "am", "gear"), ~ mtcars %>% pivot_wider(id_cols = cyl, 
  names_from = .x, values_from = .x, values_fn = length,
  names_prefix = str_c(.x, "_"), names_sort = T, values_fill = 0) %>%
  {if (.x != "vs")  select(.,-cyl) else .}) %>% arrange(cyl)

#> This message is displayed once per session.
#> # A tibble: 3 × 8
#>     cyl  vs_0  vs_1  am_0  am_1 gear_3 gear_4 gear_5
#>   <dbl> <int> <int> <int> <int>  <int>  <int>  <int>
#> 1     4     1    10     3     8      1      8      2
#> 2     6     3     4     4     3      2      4      1
#> 3     8    14     0    12     2     12      0      2