【问题标题】:R All possible sub-combinationsR 所有可能的子组合
【发布时间】:2016-02-26 05:37:42
【问题描述】:

我有一些看起来像这样的数据:

basin <- c("Volta","Seine","Limpopo")
c1 <- c("BEN","BEL","SA")
c2 <- c("BURK","FRA","MOZ")
c3 <- c("IVC","LUX","ZIM")
c4 <- c("GHA","NA","BOTS")
c5 <- c("MALI","NA","NA")
c6 <- c("TOGO","NA","NA")
df <- data.frame(basin, c1, c2, c3, c4, c5, c6)

    basin  c1  c2  c3   c4   c5   c6
1   Volta BEN BUR IVC  GHA MALI TOGO
2   Seine BEL FRA LUX   NA   NA   NA
3 Limpopo  SA MOZ ZIM BOTS   NA   NA

每个流域有 k 个国家。例如在第一行,我需要生成 5 个国家的所有组合,4 个国家的所有组合,等等。第二行我需要生成 2 个国家的所有组合,第三行需要生成 3 个国家和 2 个国家的所有组合。然后我想将这些子集添加为数据中的新行。

我尝试使用这个功能:

    allSubs <- function(x, k) {
  if(k > length(x)) stop('k > length(x)')
  if(choose(length(x), k)==1){
    list(as.vector(combn(x, k)))
  } else {
    cbn <- combn(x, k)
    lapply(seq(ncol(cbn)), function(i) cbn[,i])
  }
}    

但是,如果我向它提供这样的数据,我只能让它工作:

allSubs(c('BEN','BURK','IVC','GHA','MALI','TOGO'),4)

但我真的需要它来遍历数据框中的行。我很感激任何帮助。

【问题讨论】:

    标签: r combinations


    【解决方案1】:

    这是一个数据如下的解决方案(您的输入数据仍然有点问题,我修改了代码以生成正确的数据):

    basin <- c("Volta","Seine","Limpopo")
    c1 <- c("BEN","BEL","SA")
    c2 <- c("BURK","FRA","MOZ")
    c3 <- c("IVC","LUX","ZIM")
    c4 <- c("GHA",NA,"BOTS")
    c5 <- c("MALI",NA,NA)
    c6 <- c("TOGO",NA,NA)
    df <- data.frame(basin, c1, c2, c3, c4, c5, c6, stringsAsFactors = FALSE)
    
        basin  c1   c2  c3   c4   c5   c6
    1   Volta BEN BURK IVC  GHA MALI TOGO
    2   Seine BEL  FRA LUX <NA> <NA> <NA>
    3 Limpopo  SA  MOZ ZIM BOTS <NA> <NA>
    
    apply(df[, 2:7], 1, function(x) {l <- x[!is.na(x)]; sapply(seq(1:(length(l)-1)), function(y) combn(l, y))})
    

    结果将是每行每个国家/地区代码的各种子组合。希望这可以帮助。当然,您可以将我使用的“内联”函数拆分为您在 apply 调用中调用的外部函数。

    【讨论】:

    • 感谢您的回复。我调整了原始帖子中的数据以包含 NA(并且还展示了我是如何创建它的)。我不太擅长处理 R 中的数据,所以这是我的错误。我需要这种格式的数据,因为这只是我试图让代码工作时的一小部分数据。
    • 我编辑了答案以适应修改后的数据。不知道这是否是您正在寻找的输出,因为您没有指定预期的输出。
    • 太棒了!两个问题:我将如何调整它以不列出一个组合?我将其更改为sapply(seq(2:(length(l)-1)),但它并没有达到我的预期。另外,我如何将组合输出返回到数据框中?或者放入任何可以按盆地排序组合输出的数据框?
    【解决方案2】:

    这是您想要的固定个组合,而不是“n”个组合。

    expand.grid(c1, c2, c3, c4, c5, c6)
    

    我建议使用 this 将 c1、c2、c3.....cn 放在一个列表中。

    list <- mget(ls(pattern='^c\\d+'))
    

    这会根据您的环境中以字母“c”开头的对象创建一个列表,将您的数据集命名为更具体,以避免它占用以“c”开头的其他对象或您指定的任何对象。因此,只需将 c 替换为您所指对象名称的开头即可。

    expand.grid(list)
    
        c1  c2   c3   c4  c5   c6
    1   BEN BURK IVC  GHA MALI TOGO
    2   BEL BURK IVC  GHA MALI TOGO
    3    SA BURK IVC  GHA MALI TOGO
    4   BEN  FRA IVC  GHA MALI TOGO
    5   BEL  FRA IVC  GHA MALI TOGO
    6    SA  FRA IVC  GHA MALI TOGO
    7   BEN  MOZ IVC  GHA MALI TOGO
    8   BEL  MOZ IVC  GHA MALI TOGO
    9    SA  MOZ IVC  GHA MALI TOGO
    10  BEN BURK LUX  GHA MALI TOGO
    
    ...............................
    
    723  SA BURK ZIM BOTS <NA> <NA>
    724 BEN  FRA ZIM BOTS <NA> <NA>
    725 BEL  FRA ZIM BOTS <NA> <NA>
    726  SA  FRA ZIM BOTS <NA> <NA>
    727 BEN  MOZ ZIM BOTS <NA> <NA>
    728 BEL  MOZ ZIM BOTS <NA> <NA>
    729  SA  MOZ ZIM BOTS <NA> <NA>
    

    如果您想知道如何为一系列对象分配类似名称,我建议您尝试使用 assign 函数。

    这是一个例子。

    for (i in 2:ncol(df)-1) {
      assign(paste("Combo",i,sep=""), df[, i+1])
    }
    

    如果您不喜欢对变量名进行硬编码,请深思。

    对于所有可能的 1s、2s、3s、4s、5s、6s....ns 组的列表,我将不得不考虑这一点。很快就会回来。

    我在想 vegan 包中的 allPerms 函数和 dplyr 中的 group_by 包的某种组合应该可以解决问题,但我必须看看。

    【讨论】:

    • 啊,我明白了这个问题......将不得不尝试......我的坏
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-23
    • 1970-01-01
    相关资源
    最近更新 更多