r - 数据集中所有可能的组合与在 R 中按顺序排列的嵌套组
问题描述
我早些时候发布了这个问题,但经过一些评论后,我意识到需要更好地解释df
and result
。此外,我意识到可以使用简化的数据结构来实现我的目标。
我需要找到特定序列中的所有值组合。
在示例df
中,您可以看到嵌套的分组结构,其中GROUP
嵌套了SAMPLE
和SITE
。SAMPLE
我的实际数据集在 30中有 ~1000 SITE
。请注意,每个GROUP
都按顺序(1 到 3),并且该顺序需要保留在最终结果中,因为这是未来分析的关键部分。换句话说,不需要将GROUP
2 或 3放在 1 之前的组合。GROUP
每个中的、和列GROUP
中有 2 或 3 个文本或数值。比如F1有3组,每组有2种可能性:1有4个和unk_palmer_trib;2有6.1和5.2;'GROUP' 3 有 10.1 和 6.1。您可以看到B2 也有三个组,其中1 和 3 有两种可能性,而2 有三种可能性。ASSIGN_1
ASSIGN_2
ASSIGN_3
GROUP
GROUP
SAMPLE
GROUP
GROUP
所以……我需要找到ASSIGN
列中值的所有可能组合,同时保留GROUP
. 请注意,OPTION
中的列是来自 中的列result
的值的各种组合,您会注意到这些组合保留了顺序(即 1 到 3)。另请注意,包含数据的列数(即没有“NAs”)对应于保留序列的列的所有可能组合。F1 有 3 组,每组有 2 种可能性,因此有 8 种可能的结果(即 2 x 2 x 2;见第 1 至第 8 列)。ASSIGN
df
GROUP
OPTION
result
ASSIGN
GROUP
SAMPLE
OPTION
SAMPLE
B2 有 3 组(2 组有两种可能性,1 组有三种可能性),因此有 12 种可能的结果(即 2 x 3 x 2;见OPTION
第 1 至第 12 列)。
为了真正推动这一点,让我们看看SAMPLE
F1df
和result
以说明如何构建这些组合。OPTION_1
因为 F1 只是ASSIGN_1
来自 的列df
。OPTION_2
是来自ASSIGN_1
(即,GROUP_1 = 4)的第 1 行,然后是来自 ASSIGN_2 的第 2 行和第 3 行(即,GROUP_2 = 5.2 和 GROUP_3 = 6.1)。'OPTION_3' 是来自ASSIGN_1
(即,GROUP_1 = 4)的第 1 行,来自ASSIGN_2
(即,GROUP_2 = 5.2)的第 2 行和来自ASSIGN_1
(即,GROUP_3 = 10.1)的第 3 行。在恶心处重复……
在我的实际数据集中,其中一些GROUP
最多可以有 5ASSIGN
列……所以可能的组合数量对于某些SAMPLE
.
我曾尝试使用expand.grid()
within ave()
,但无法使代码正常工作。我对所有解决方案持开放态度,但更喜欢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=
参数是需要在组合中保留而不是扩展的字段的整数向量。
示范:
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)
推荐阅读
- twitter - Zapier:如何从 trello 多个图像附件发布推文?
- for-loop - 如何让它自己重置?堆叠十六进制数
- linux - 您如何迭代按顺序编号的环境变量?
- json - 将 JSON 对象和数组转换为 VB.net 中的同一类
- java - 外部缓存目录绕过 Android 10 无法在主目录上执行文件
- angular - 用于 Angular 动画的 MDB Bootstrap 不起作用
- python - 尝试使用 Pandas 操作传感器时间数据
- html - 通过将额外参数附加到 URL 来更改网页元素的外观
- mysql - MYSQL 数学在表中的单个列中。子查询未正确分组
- database - 将 shapefile 导入数据库并在 ArcGIS Online 中访问此数据