繁体   English   中英

数据集中所有可能的组合与嵌套组在 R 中按顺序排列

[英]All possible combinations in data set with nested groups that are ordered sequencially in R

我早些时候发布了这个问题,但经过一些评论后,我意识到需要对dfresult进行更好的解释。 此外,我意识到可以使用简化的数据结构来实现我的目标。

我需要找到特定序列中的所有值组合。

在示例df中,您可以看到嵌套的分组结构,其中GROUP嵌套在SAMPLESITE中。 我的实际数据集在 30 个SITE中有 ~1000 SAMPLE 请注意,每个GROUP都是按顺序排列的(1 到 3),并且该顺序需要保留在最终结果中,因为这是未来分析的关键部分。 换句话说,不需要将GROUP 2 或 3 放在GROUP 1 之前的组合。

每个GROUPASSIGN_1ASSIGN_2ASSIGN_3列中有 2 或 3 个文本或数值。 比如F1有3组,每组有2种可能性: GROUP 1有4个和unk_palmer_trib; 第 2 GROUP有 6.1 和 5.2; 'GROUP' 3 有 10.1 和 6.1。 您可以看到SAMPLE B2 也有三个GROUP ,第 1 组和第 3 组有两种可能性,第 2 GROUP有三种可能性。

所以……我需要找到ASSIGN列中所有可能的值组合,同时保留GROUP的序列。 请注意, result中的OPTION列是dfASSIGN列的值的各种组合,您会注意到这些组合保留了GROUP序列(即 1 到 3)。 另请注意, result中包含数据的OPTION列数(即没有“NAs”)对应于保留GROUP序列的ASSIGN列的所有可能组合。 SAMPLE F1 有 3 组,每组有 2 种可能性,因此有 8 种可能的结果(即 2 x 2 x 2;参见OPTION列 1 至 8)。 SAMPLE B2 有 3 组(2 组有两种可能性,1 组有三种可能性),因此有 12 种可能的结果(即 2 x 3 x 2;参见OPTION列 1 至 12)。

为了真正推动这一点,让我们看看df中的SAMPLE F1 和result ,以说明如何构建这些组合。 F1 的OPTION_1只是dfASSIGN_1列。 OPTION_2ASSIGN_1的第 1 行(即 GROUP_1 = 4),然后是 ASSIGN_2 的第 2 行和第 3 行(即 GROUP_2 = 5.2 和 GROUP_3 = 6.1)。 'OPTION_3' 是ASSIGN_1的第 1 行(即 GROUP_1 = 4)、 ASSIGN_2的第 2 行(即 GROUP_2 = 5.2)和ASSIGN_1的第 3 行(即 GROUP_3 = 10.1)。 在恶心处重复……

在我的实际数据集中,某些GROUP最多可以有 5 个ASSIGN列……因此对于某些SAMPLE可能的组合数量可能很大。

我尝试在ave()中使用expand.grid() ) ,但无法使代码正常工作。 我对所有解决方案持开放态度,但更喜欢base package解决方案,因为我想避免加载包。 我还怀疑df可能需要以某种方式进行重组……只要GROUP序列保留在最终产品中,这完全没问题。

让我知道是否需要澄清。

在此先感谢您的帮助。

df <- read.table(text = "SITE   SAMPLE  GROUP   ASSIGN_1    ASSIGN_2    ASSIGN_3
A1  F1  1   4   unk_palmer_trib NA
A1  F1  2   6.1 5.2 NA
A1  F1  3   10.1    6.1 NA
M15 B2  1   6.2 6.4 NA
M15 B2  2   10.1    6.1 5.2
M15 B2  3   10.1    6.1 NA
", header = TRUE)

result <- read.table(text = "SITE   SAMPLE  GROUP   OPTION_1    OPTION_2    OPTION_3    OPTION_4    OPTION_5    OPTION_6    OPTION_7    OPTION_8    OPTION_9    OPTION_10   OPTION_11   OPTION_12
A1  F1  1   4   4   4   4   unk_palmer_trib unk_palmer_trib unk_palmer_trib unk_palmer_trib NA  NA  NA  NA
A1  F1  2   6.1 5.2 5.2 6.1 6.1 5.2 5.2 6.1 NA  NA  NA  NA
A1  F1  3   10.1    6.1 10.1    6.1 10.1    6.1 10.1    6.1 NA  NA  NA  NA
M15 B2  1   6.2 6.2 6.2 6.2 6.2 6.2 6.4 6.4 6.4 6.4 6.4 6.4
M15 B2  2   10.1    6.1 10.1    6.1 5.2 5.2 10.1    6.1 10.1    6.1 5.2 5.2
M15 B2  3   10.1    6.1 6.1 10.1    10.1    6.1 10.1    6.1 6.1 10.1    10.1    6.1
", header = TRUE)

这是一个刺:-)

func <- function(x, keep = integer(0)) {
  if (length(keep)) {
    saved <- x[,keep,drop=FALSE]
    x <- x[,-keep]
  } else {
    saved <- x[,0] # empty column
  }
  out <- t(do.call(expand.grid, asplit(t(x), 2)))
  out <- as.data.frame(out[, colSums(is.na(out)) == 0])
  colnames(out) <- paste0("OPTION_", seq_along(out))
  cbind(saved, out)
}

keep=参数是需要在组合中保留而不是扩展的字段的 integer 向量。

示范:

LOF <- Filter(length, by(df, df[,c("SITE","SAMPLE")], FUN = func, keep = 1:3))
allnames <- unique(unlist(lapply(LOF, colnames)))
LOF <- lapply(LOF, function(z) { z[setdiff(allnames, colnames(z))] <- NA; z; })
do.call(rbind, LOF)
#   SITE SAMPLE GROUP OPTION_1        OPTION_2 OPTION_3        OPTION_4 OPTION_5        OPTION_6 OPTION_7        OPTION_8 OPTION_9 OPTION_10 OPTION_11 OPTION_12
# 4  M15     B2     1      6.2             6.4      6.2             6.4      6.2             6.4      6.2             6.4      6.2       6.4       6.2       6.4
# 5  M15     B2     2     10.1            10.1      6.1             6.1      5.2             5.2     10.1            10.1      6.1       6.1       5.2       5.2
# 6  M15     B2     3     10.1            10.1     10.1            10.1     10.1            10.1      6.1             6.1      6.1       6.1       6.1       6.1
# 1   A1     F1     1      4.0 unk_palmer_trib      4.0 unk_palmer_trib      4.0 unk_palmer_trib      4.0 unk_palmer_trib     <NA>      <NA>      <NA>      <NA>
# 2   A1     F1     2      6.1             6.1      5.2             5.2      6.1             6.1      5.2             5.2     <NA>      <NA>      <NA>      <NA>
# 3   A1     F1     3     10.1            10.1     10.1            10.1      6.1             6.1      6.1             6.1     <NA>      <NA>      <NA>      <NA>

如果您已经在使用data.table ,那么这可以简化为第一个加上第二个或第三个:

LOF <- Filter(length, by(df, df[,c("SITE","SAMPLE")], FUN = func, keep = 1:3))
data.table::rbindlist(LOF, fill = TRUE, use.names = TRUE)
dplyr::bind_rows(LOF)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM