所有R可能子组合

问题描述:

我有一些数据,看起来像这样:所有R可能子组合

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) 

但我真的需要它遍历通过数据框中的行。我感谢任何帮助。

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

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调用的外部函数的'inline'函数分开。

+0

谢谢你的回应。我调整了原始文章中的数据以包含NAs(并且还显示了我是如何创建的)。我不擅长处理R中的数据,这是我的错误。我需要这种格式,因为这只是数据的一小部分,而我试图让代码工作。 – Beatrix

+0

我编辑了答案以适应修改后的数据。不知道这是你正在寻找的输出,因为你没有指定预期的输出。 – Gopala

+0

太棒了!两个问题:我将如何调整它以不列出一个组合?我将它改为'sapply(seq(2:(length(l)-1))',但它没有做到我想的那样。另外,我怎样才能将组合输出返回到数据框?任何数据框,可以命令盆地的组合输出? – Beatrix

这里是你想要的固定组合的数量,而不是“n”组合的数量。

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

我建议把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> 

如果你想知道如何分配similiar一系列的名字,我建议用玩弄周围的物体分配功能。

下面是一个例子。

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

如果您不喜欢硬编码变量名称,那么只需要考虑一下。

有关1s,2s,3s,4s,5s,6s .... ns的所有可能组的列表,我将不得不考虑这一点。将尽快回复。

我正在考虑allPerms函数素食包和group_by包在dplyr中的一些组合应该做的伎俩,但我必须看到。

+0

啊,我看到的问题...将不得不实验...我的坏 – InfiniteFlashChess