跨多个列,计算对的实例

Across several columns, count instances of pairs

我想计算几列中的对数。也就是说,对于超过两列,计算特定值对在同一行中出现的次数。

假设我问一些人是否喜欢不同种类的食物,他们可以回答“是”或“否”。我最终得到了这个数据集:

foods <- 
  data.frame(
    fruit = c("yes", "yes", "no"),
    veg = c("yes", "yes", "yes"),
    meat = c("yes", "no", "yes")
  )
foods

我想计算任意两种食物获得“是”的次数。我希望以这样的方式结束:

desired <- 
  data.frame(
    pair.1 = c("fruit", "fruit", "veg"),
    pair.2 = c("veg", "meat", "meat"),
    Freq = c(2, 1, 2)
  )
desired

这也可行:

desired.2 <- 
  data.frame(
    pair. = c("fruit, veg", "fruit, meat", "veg, meat"),
    Freq = c(2, 1, 2)
  )
desired.2

如果可能的话,我希望我可以使用一种解决方案最终对 3、4 等的组合执行相同的操作(我的实际数据有 3 列以上)。有什么好的解决方案,最好使用 dplyr?

预先感谢您的帮助!

一个dplyrpurrr的解决方案可以是:

map_dfr(.x = combn(names(foods), 2, simplify = FALSE),
        ~ foods %>%
         select(.x) %>%
         summarise(pair_1 = .x[1],
                   pair_2 = .x[2],
                   n = sum(rowSums(select(., everything()) == "yes") == 2)))

  pair_1 pair_2 n
1  fruit    veg 2
2  fruit   meat 1
3    veg   meat 2

如果你想要更通用的东西:

fun <- function(x) {
map_dfr(.x = combn(names(foods), x, simplify = FALSE),
        ~ foods %>%
         select(.x) %>%
         summarise(pairs = paste(.x, collapse = " "),
                   n = sum(rowSums(select(., everything()) == "yes") == x)))
}

fun(2)

       pairs n
1  fruit veg 2
2 fruit meat 1
3   veg meat 2

您可以使用combn,即

combn(names(foods), 2, FUN = function(i){i1 <- foods[i]; sum(i1[1] == i1[2])})
#[1] 2 1 2

对于成对的人,听起来您正在寻找 crossprod:

crossprod(foods == "yes")
#       fruit veg meat
# fruit     2   2    1
# veg       2   3    2
# meat      1   2    2

注意上面结果的upper.trilower.tri

如果我们将结果视为 table,我们可以将其包装在 data.frame 中并仅提取那些特定的对:

x <- crossprod(foods == "yes")
data.frame(as.table(x))[lower.tri(x), ]
#   Var1  Var2 Freq
# 2  veg fruit    2
# 3 meat fruit    1
# 6 meat   veg    2