如何计算列表中每个项目与其他每个项目同时出现的次数?

swr*_*swr 1 r count

在这个一般领域有很多问题都有很好的解决方案,但我很难将它们应用到我的数据中。我有长格式数据,其中一列为我们提供观察结果,另一列为我们提供观察结果中的成员。我想做的就是计算每个成员与其他成员同时出现的次数。

\n

假设我有以下数据集:

\n
df <- data.frame(salad = c(rep("Green", 4), rep("Caprese", 3), rep("Fruit", 3)),\n                 ingredients = c("Lettuce", "Tomato", "Onion", "Olives",\n                                 "Tomato", "Onion", "Mozzarella",\n                                 "Melon", "Orange", "Tomato"))\n\ndf\n\n     salad ingredients\n1    Green     Lettuce\n2    Green      Tomato\n3    Green       Onion\n4    Green      Olives\n5  Caprese      Tomato\n6  Caprese       Onion\n7  Caprese  Mozzarella\n8    Fruit       Melon\n9    Fruit      Orange\n10   Fruit      Tomato\n
Run Code Online (Sandbox Code Playgroud)\n

我想要做的是生成一个包含所有可能的成员(成分)组合的表格,并计算它们在观察(沙拉)中同时出现的次数。它看起来像这样:

\n
results\n\n    ingredient_A     ingredient_B      count\n1   Lettuce          Tomato            1\n2   Lettuce          Onion             1\n3   Lettuce          Olives            1\n4   Lettuce          Mozzarella    0\n5   Lettuce          Melon             0\n6   Lettuce          Orange            0\n7   Tomato           Onion             2\n8   Tomato           Olives            1\n9   Tomato           Mozzarella    1\n10  Tomato           Melon             1\n\xe2\x80\xa6   \xe2\x80\xa6            \xe2\x80\xa6             \xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n

我觉得答案非常简单,但我现在遇到了困难。任何帮助,将不胜感激。

\n

r2e*_*ans 8

这是 dplyr/tidyr 方法:

library(dplyr)
library(tidyr)
df %>%
  left_join(., ., by = join_by(salad, ingredients < ingredients), suffix = c("_A", "_B")) %>%
  filter(complete.cases(.)) %>%
  count(ingredients_A, ingredients_B, name = "count")
#    ingredients_A ingredients_B count
# 1        Lettuce        Olives     1
# 2        Lettuce         Onion     1
# 3        Lettuce        Tomato     1
# 4          Melon        Orange     1
# 5          Melon        Tomato     1
# 6     Mozzarella         Onion     1
# 7     Mozzarella        Tomato     1
# 8         Olives         Onion     1
# 9         Olives        Tomato     1
# 10         Onion        Tomato     2
# 11        Orange        Tomato     1
Run Code Online (Sandbox Code Playgroud)

left_join(., ., ...)是一个自连接,使用两个.只是为了意图和清晰。这ingredients < ingredients让我们确信我们没有自连接 ( ) 以及每个 中的配对 (和)Tomato, Tomato的双方。Tomato, LettuceLettuce, Tomatosalad

也许有点忙,基本的 R 变体可能是:

split(df, df$salad) |>
  lapply(function(z) merge(z, z, by = "salad", suffix = c("_A", "_B")) |>
  subset(ingredients_A < ingredients_B)) |>
  do.call(what = rbind.data.frame) |>
  xtabs(~ ingredients_A + ingredients_B, data = _) |>
  as.data.frame.table(responseName = "count") |>
  subset(count > 0)
#    ingredients_A ingredients_B count
# 1        Lettuce        Olives     1
# 7        Lettuce         Onion     1
# 9     Mozzarella         Onion     1
# 10        Olives         Onion     1
# 14         Melon        Orange     1
# 19       Lettuce        Tomato     1
# 20         Melon        Tomato     1
# 21    Mozzarella        Tomato     1
# 22        Olives        Tomato     1
# 23         Onion        Tomato     2
# 24        Orange        Tomato     1
Run Code Online (Sandbox Code Playgroud)

base-R 变体执行完整的笛卡尔连接(在每个沙拉中),这意味着如果实际数据中每个沙拉的成分数量相当大,这可能会变得昂贵。

更重要的是,因为任何行为都不需要只是两种方言;-)

library(data.table)
DT <- as.data.table(df)
DT <- as.data.table(df)
DT[, int := match(ingredients, sort(unique(ingredients)))
  ][DT, on = .(salad, int < int)
  ][!is.na(ingredients), .(count = .N), by = .(ingredients, i.ingredients)]
#     ingredients i.ingredients count
#          <char>        <char> <int>
#  1:     Lettuce        Tomato     1
#  2:       Onion        Tomato     2
#  3:      Olives        Tomato     1
#  4:     Lettuce         Onion     1
#  5:      Olives         Onion     1
#  6:     Lettuce        Olives     1
#  7:  Mozzarella        Tomato     1
#  8:  Mozzarella         Onion     1
#  9:       Melon        Orange     1
# 10:       Melon        Tomato     1
# 11:      Orange        Tomato     1
Run Code Online (Sandbox Code Playgroud)

我补充说int,因为data.table支持不等式连接,但不支持字符串;因此,int < int类似于 dplyr 的ingredients < ingredients.

sort(.)我在计算中包含的唯一原因int是为了使输出更接近其他两种方言;虽然结果实际上是相同的,但Onion, Tomato也可能是Tomato, Onion。如果这很重要的话就交给你了。

  • 这个“自加入”太棒了,以前没想过 (2认同)
  • @GuedesBF 它可能会变得昂贵,我希望真实数据不会爆炸...... (2认同)