【问题标题】:All possible combinations in data set with nested groups that are ordered sequencially in R数据集中所有可能的组合与在 R 中按顺序排列的嵌套组
【发布时间】:2021-05-06 01:22:02
【问题描述】:

我早些时候发布了这个问题,但在几次 cmet 之后,我意识到需要更好地解释 dfresult。此外,我意识到可以使用简化的数据结构来实现我的目标。

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

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

每个GROUP 中的ASSIGN_1ASSIGN_2ASSIGN_3 列中有2 或3 个文本或数值。比如F1有3组,每组有2种可能:GROUP1有4个,unk_palmer_trib; GROUP2 有 6.1 和 5.2; 'GROUP' 3 有 10.1 和 6.1。可以看到SAMPLEB2也有三组,GROUP1和3有两种可能,GROUP2有三种可能。

所以……我需要找到ASSIGN 列中所有可能的值组合,同时保留GROUP 的序列。请注意,result 中的OPTION 列是来自dfASSIGN 列的值的各种组合,您会注意到这些组合保留了GROUP 序列(即1 到3)。另请注意,result 中包含数据(即没有“NAs”)的OPTION 列的数量对应于保留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 列)。

要真正强调这一点,让我们看一下dfresult 中的SAMPLE F1,以说明如何构建这些组合。 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)

【问题讨论】:

    标签: r


    【解决方案1】:

    这是一个刺:-)

    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= 参数是需要在组合中保留和扩展的字段的整数向量。

    演示:

    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)
    

    【讨论】:

    • 代码运行良好!谢谢传奇。保重。
    猜你喜欢
    • 2014-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2014-02-19
    • 2018-11-29
    相关资源
    最近更新 更多