【问题标题】:Getting distinct Combinations in R with repetition在 R 中通过重复获得不同的组合
【发布时间】:2018-04-16 22:29:53
【问题描述】:

我有一个整数列表,比如:(1,2,3,4,5)

我想获取所有可能的大小为 5 的列表,例如:

1. 列表可以包含重复元素,例如(1,1,1,2,2)

2. 排序无关紧要,例如(1,1,2,2,1) 与 (1,1,1,2,2) 相同

如何获取整个列表?我实际上是在从一组 10 个整数中寻找大小为 10 的组合。

【问题讨论】:

标签: r combinations


【解决方案1】:

使用推荐的RcppAlgos 解决方案in this answer,我们希望从您的输入中选择5 个元素的集合,重复,并且顺序无关紧要(因此comboGeneral(),如果顺序很重要,我们将使用permuteGeneral() )。在引擎盖下用 C++ 编码,这将是一个非常快速的解决方案,并且链接答案中的分析也发现它具有内存效率。在我的笔记本电脑上为 10 多选 10 生成集合仍然不到一秒钟。

library(RcppAlgos)
x = 1:5
result = comboGeneral(x, m = 5, repetition = T)
dim(result)
# [1] 126   5
head(result)
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    1    1    1    1
# [2,]    1    1    1    1    2
# [3,]    1    1    1    1    3
# [4,]    1    1    1    1    4
# [5,]    1    1    1    1    5
# [6,]    1    1    1    2    2

【讨论】:

  • @KohLP 这是您正在寻找的答案。
【解决方案2】:

Gregor 提供的链接似乎完全依赖第三方包来产生多集,所以我想给你一个基本的 R 解决方案。请注意,该链接中提到的软件包对于超大型数据集几乎肯定会更有效。

我们可以使用expand.grid() 首先生成所有可能的排列,其中重复 (1,2,3,4,5) 中的元素。在这种情况下,不同的排序仍然被认为是不同的。我们现在要删除这些包含相同元素但顺序不同的“额外”组合,我们可以使用apply()duplicated() 来完成。

如果您使用多重集计算器here,您会发现下面的代码产生了正确数量的组合。代码如下:

x <- seq(1:5)

df <- expand.grid(x, x, x, x, x) # generates 5^5 combinations, allowing repetition

index <- !duplicated(t(apply(df, 1, sort))) # find extraneous combinations
df <- df[index, ] # select only unique combinations

# check number of rows. It should be 126; one for each combination
nrows(df)

# Output
# [1] 126

# Quick look at part of the dataframe:

head(df)
  Var1 Var2 Var3 Var4 Var5
1    1    1    1    1    1
2    2    1    1    1    1
3    3    1    1    1    1
4    4    1    1    1    1
5    5    1    1    1    1
7    2    2    1    1    1

【讨论】:

  • 非常感谢您的帮助。这就是我想要达到的目的。我实际上正在寻找 10^10,我认为这不可行。我正在查看 multisets 页面,这让我有点不知所措。你会推荐这些包中的任何一个吗?好像 iterpc 是要使用的,但我不知道它有什么作用。
  • iterpc 对我来说看起来不错,但老实说,我对这些软件包没有经验。抱歉-我认为您的实际问题在规模上与您的玩具数据更接近。就我个人而言,我会推荐 Maurits Evers 的解决方案。它更节省内存。但是请注意,它仍然需要大量的计算机内存。
【解决方案3】:

对于@MarcusCampbell 在tidyverse 中的类似方法,我们可以使用expand 来枚举所有可能的组合,然后只保留在排列下不变的distinct 组合(即排序无关紧要) :

library(tidyverse);
tibble(V1 = 1:5, V2 = 1:5, V3 = 1:5, V4 = 1:5, V5 = 1:5) %>%
    expand(V1, V2, V3, V4, V5) %>%
    rowwise() %>%
    mutate(cmbn = paste(sort(c(V1, V2, V3, V4, V5)), collapse = ",")) %>%
    distinct(cmbn);
    ## A tibble: 126 x 1
    #   cmbn
    #   <chr>
    # 1 1,1,1,1,1
    # 2 1,1,1,1,2
    # 3 1,1,1,1,3
    # 4 1,1,1,1,4
    # 5 1,1,1,1,5
    # 6 1,1,1,2,2
    # 7 1,1,1,2,3
    # 8 1,1,1,2,4
    # 9 1,1,1,2,5
    #10 1,1,1,3,3
    ## ... with 116 more rows

【讨论】:

  • 对于阅读这些答案的任何人来说,这是一个比我更好的解决方案。我没有时间对其进行基准测试,但它的内存效率可能比我的方法高出大约一个数量级。
猜你喜欢
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 2014-02-15
  • 2019-06-23
  • 1970-01-01
  • 2020-05-02
  • 2017-10-30
相关资源
最近更新 更多