簡體   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