【问题标题】:Create n Combinations Using While Loop in R在 R 中使用 While 循环创建 n 个组合
【发布时间】:2016-01-11 11:29:20
【问题描述】:

从城市、条件和订单号的数据框开始,我正在尝试按城市和条件创建 n 个可能的订单号组合([1]、[2]、[3 ]、[1]&[2]、[1]&[3]、[2]&[3]、[1]&[2]&[3])。

library(gtools)
set.seed(123)
dat <- data.frame(City = c(rep("St. Louis", 3), rep("Chicago", 2)), 
              Condition = c(rep("A", 3), rep("B", 2)),
              Order.No = round(runif(5,10,100),0))

按城市和条件划分:

dat_groups <- lapply(split(dat, list(dat$City, dat$Condition)), function(x) {
    x$Order.No
})

> dat_groups
$Chicago.A
numeric(0)

$`St. Louis.A`
[1] 36 81 47

$Chicago.B
[1] 89 95

$`St. Louis.B`
numeric(0)

我可以使用带有“combn”的 while() 循环作为 n 的容器来接近组合解决方案,但是我无法将输出保存到列表对象以可接受的格式。

combn <- 4
counter <- 0
while (counter <= combn) {
    counter <- counter + 1
    temp <- lapply(dat_groups, function(x) {
        n_obs <- length(x)
        if(n_obs == 0) {
            NA
        }
            if(n_obs > 0 & n_obs >= counter) {
                combinations(n_obs, counter, x)       
            } else {
                NA
            }
        })
print(temp)
}

$Chicago.A
[1] NA

$`St. Louis.A`
     [,1]
[1,]   36
[2,]   47
[3,]   81

$Chicago.B
     [,1]
[1,]   89
[2,]   95

$`St. Louis.B`
[1] NA

$Chicago.A
[1] NA

$`St. Louis.A`
     [,1] [,2]
[1,]   36   47
[2,]   36   81
[3,]   47   81

$Chicago.B
     [,1] [,2]
[1,]   89   95

$`St. Louis.B`
[1] NA

$Chicago.A
[1] NA

$`St. Louis.A`
     [,1] [,2] [,3]
[1,]   36   47   81
...............
truncated

上面的代码通过列出所有单个组合来接近,然后是每个城市和条件的双打,然后是三倍,但我不知道如何删除 NA,关闭漏洞,然后保存到列表中像下面这样的对象。

所需的最终解决方案应如下所示:

[[1]]
[1] "36"

[[2]]
[1] "81"

[[3]]
[1] "47"

[[4]]
[1] "36" "81"

[[5]]
[1] "36" "47"

[[6]]
[1] "81" "47"

[[7]]
[1] "36" "81" "47"

[[8]]
[1] "89"

[[9]]
[1] "95"

[[10]]
[1] "89" "95"

感谢您查看并提供任何帮助。

【问题讨论】:

    标签: r loops while-loop combinations


    【解决方案1】:

    您可以使用dplyr 获取列表的data.frame:

    library(dplyr)
    newdat <- dat %>% group_by(City, Condition) %>%
                      summarise(lists = list(lapply(1:n(), 
                                function(z){combinations(v=Order.No, r=z, n=n())}))) 
    newdat
    Source: local data frame [2 x 3]
    Groups: City [?]
    
           City Condition     lists
         (fctr)    (fctr)     (chr)
    1   Chicago         B <list[2]>
    2 St. Louis         A <list[3]>
    

    newdat$lists 列现在在列表中包含 City:Condition 的每个级别的所有子样本。

    要获得与您想要的输出相同的格式,我们需要做一些列表整理:

    unlist(lapply(unlist(newdat$lists, recursive = FALSE), 
                   function(x){as.list(data.frame(t(x)))}), recursive = FALSE)
    $X1
    [1] 89
    
    $X2
    [1] 95
    
    $t.x.
    [1] 89 95
    
    $X1
    [1] 36
    
    $X2
    [1] 47
    
    $X3
    [1] 81
    
    $X1
    [1] 36 47
    
    $X2
    [1] 36 81
    
    $X3
    [1] 47 81
    
    $t.x.
    [1] 36 47 81
    

    编辑:作为一个函数:

    lister <- function(data, numgroups){
        data %>% group_by(City, Condition) %>%
            summarise(lists = list(lapply(1:min(numgroups, n()), 
                                          function(z){combinations(v=Order.No, r=z, n=n())}))) 
    }
    

    例如:

    lister(dat, 2)
    

    【讨论】:

    • 感谢@jeremycg 的回复。使用 n() 不会总是导致使用每个城市/条件组的所有订单号吗?这是我问题的核心。我需要能够设置变量 n 并将其应用于每个组,而不管每个组有多少订单号。即第一组有 15 个订单号和 n=2,所以我只想查看所有 1:2 组合,而不是 1:15 组合。
    • 当然,在这种情况下,将n() 更改为您想要的数字,或者使用function(numberofrepeats) .... 将整个内容包装在一个函数中,并将两个n()s 替换为您的变量
    • 抱歉,我对 goup_by 不熟悉,所以我正在为如何将您的代码包装在另一个函数中而苦苦挣扎。我很确定它必须在 function() 中,尽管有某种 if() else 有条件的,因为如果给定组的订单数小于 n 它会爆炸.
    • 没问题:查看编辑 - 我用过 min,所以它取较低的、要求的组或 n()。
    • 我认为解决方法是将n=min(numgroups, n()) 更改为n=n()?我会编辑答案
    猜你喜欢
    • 1970-01-01
    • 2020-11-27
    • 2010-10-13
    • 2015-11-23
    • 2012-10-07
    • 1970-01-01
    • 2023-03-22
    • 2011-03-05
    • 2015-06-23
    相关资源
    最近更新 更多