按组查找向量中最常见的组合

Posted

技术标签:

【中文标题】按组查找向量中最常见的组合【英文标题】:Find Most Frequent Combination within a Vector by Group 【发布时间】:2017-02-06 12:29:15 【问题描述】:

我有一个包含两列的表格,即iditem

df <- data.frame(id=c(1,1,2,2,2,2,3,3,3,4,4,4,4,4),item=c(1,2,3,1,2,3,4,1,2,3,1,2,1,2))

我想为每个id 找到 3 个项目的最频繁组合(顺序无关紧要)。所以基本上,n 选择r 其中n = number of items within idr = 3。每个 id 的项目数量各不相同 - 有些超过 3 个,有些则更少。

我是 R 新手,阅读了有关 combnexpand.grid 的信息,但我不知道如何在我的情况下使用它们(在每个 id 中工作)。

“Find most frequent combination of values in a data.frame”是我找到的最接近的问题。

编辑:基于示例的预期答案是组合“1、2、3”,它出现在 id 2 和 4 中。

【问题讨论】:

请将基于示例数据的预期结果添加到您的问题中 n choose r 不会返回一个数字吗?您可以使用@Stephen 回答group_by(id) 找到每个id 的项目数。您是否要考虑 3 个数字的所有排列,并显示 n choose r 可能性中出现频率最高的一个? 【参考方案1】:

这是一个使用dplyr的想法

df1 <- df %>% 
        group_by(id) %>% 
        arrange(item) %>% 
        summarise(new = paste(unique(combn(item, length(unique(item)), toString)), collapse = '/'))
df1
# A tibble: 4 × 2
#     id                                             new
#  <dbl>                                           <chr>
#1     1                                            1, 2
#2     2                     1, 2, 3 / 1, 3, 3 / 2, 3, 3
#3     3                                         1, 2, 4
#4     4 1, 1, 2 / 1, 1, 3 / 1, 2, 2 / 1, 2, 3 / 2, 2, 3

names(sort(table(unlist(strsplit(df1$new, '/'))), decreasing = TRUE)[1])
#[1] "1, 2, 3"

【讨论】:

非常感谢。这是一个很好的解决方案。我一定遗漏了一些东西,因为我得到了完全相同的df1,但是当我运行最后一位names(... 时,我得到了[1] " 1, 1, 3 "【参考方案2】:
library(dplyr)
grouped <- df %>% group_by(id,item) %>% summarize(count = n()) %>% arrange(desc(count))

瞧。最高计数从高到低排序。

编辑:刚刚意识到我没有完全回答你的问题。我希望我给了你一个好的开始。

【讨论】:

感谢您的快速回答。我只是按照要求添加了预期的结果。我正在寻找最频繁的项目组合,而不是最频繁的项目。【参考方案3】:

我认为这是你想要使用 base R 的(不需要包):

a <- aggregate(item~id, df, unique)
a <- lapply(a$item, 'length<-', max(lengths(a$item)))
m <- matrix(unlist(a), ncol=3, byrow = T)
m <- t(apply(m,1,function(x) sort(x,na.last = T)))

#     [,1] [,2] [,3]
#[1,]    1    2   NA
#[2,]    1    2    3
#[3,]    1    2    4
#[4,]    1    2    3

一旦我们得到矩阵m,矩阵中出现频率最高的行就是你想要的:

t <- table(apply(m, 1, paste, collapse = "/")) 
as.numeric(strsplit(names(which.max(t)), "/")[[1]]) 

#[1] 1 2 3

【讨论】:

感谢您的回答,但我不知道聚合如何处理 id 中可能的不同组合。它似乎只需要每个中的前 3 个项目。 @DGenchev 更新了我的帖子。由于它会根据 id 查找唯一元素,因此您看到的顺序是偶然的,如果您更改原始 df 中的顺序,您会看到它按预期工作。 好的,我想我现在明白了。但是,如果一个组碰巧拥有比所有其他组更多的项目,它将失败(即,所有其他组将具有 NA,而拥有更多项目的组将被放在顶部)。我通过使用id = 4item = 5 再添加一条记录来测试它

以上是关于按组查找向量中最常见的组合的主要内容,如果未能解决你的问题,请参考以下文章

R中的按组组合

在 R 中按组创建组合

查找字符串中最重复(不是最常见)序列的算法(也称为串联重复)

按组查找最近的日期和输出值

在 data.frame 中查找最常见的值组合

在 MATLAB 中查找互补向量的快速方法