如何在R语言中递归将2D矩阵转换为3D数组?
问题:将2D矩阵递归转换为3D数组(适配任意第三维度层级)
我有一个2D矩阵,想要将其转换为3D数组,当前的转换逻辑存在问题。目标是实现可递归的转换逻辑,适配任意数量的第三维度层级。
原始数据
dfs <- (structure(c(-0.046, 0.676, -0.698, -0.047, 0.719, -0.646, -0.044, 0.706, -0.667, 0.046, 0.769, -0.605, 0.047, 0.813, -0.551, 0.044, 0.795, -0.578), dim = c(9L, 2L), dimnames = list(c("snatch:(Intercept)", "snatch:weight", "snatch:age", "clean:(Intercept)", "clean:weight", "clean:age", "total:(Intercept)", "total:weight", "total:age" ), c("2.5 %", "97.5 %"))))
期望输出格式
$a X2.5% X97.5% (Intercept) -0.046 0.046 weight 0.676 0.769 age -0.698 -0.605 $b X2.5% X97.5% (Intercept) -0.047 0.047 weight 0.719 0.813 age -0.646 -0.551 $c X2.5% X97.5% (Intercept) -0.044 0.044 weight 0.706 0.795 age -0.667 -0.578
当前尝试的代码
rnames <- c("(Intercept)", "snatch", "age") cnames <- colnames(dfs); cnames lnames <- c("a", "b", "c"); lnames array( data = matrix(data = type.convert(gsub("^[^:]+:\s*", "", dfs), as.is=TRUE), nrow=nrow(dfs), ncol=ncol(dfs)), dim = c(nrow(dfs)/length(lnames), length(cnames), length(lnames)), dimnames = list(rows=rnames, column=cnames, level=lnames)) %>% apply(., 2, data.frame)
解决方案
核心思路
- 从行名中拆分出分组标识(如
snatch/clean/total)和行子项(如(Intercept)/weight/age) - 依据分组标识自动拆分原始矩阵,无需硬编码分组数量,适配任意第三维度层级
- 重组为匹配期望格式的列表或3D数组
实现代码
方法一:动态生成匹配期望格式的列表
# 拆分行名,提取分组和子项信息 row_parts <- strsplit(rownames(dfs), ":") groups <- sapply(row_parts, `[`, 1) sub_rows <- sapply(row_parts, `[`, 2) # 按分组拆分矩阵,并重命名行、列 result <- lapply(split(seq_along(groups), groups), function(idx) { mat <- dfs[idx, , drop = FALSE] rownames(mat) <- sub_rows[idx] colnames(mat) <- gsub(" ", "X", colnames(mat)) # 替换列名空格为X,匹配期望格式 mat }) # 给列表元素命名为a/b/c names(result) <- c("a", "b", "c") # 查看结果 print(result)
方法二:生成支持任意层级的3D数组
如果需要严格的3D数组结构,可使用以下代码,自动计算维度:
# 提取分组和子项信息 row_parts <- strsplit(rownames(dfs), ":") groups <- factor(sapply(row_parts, `[`, 1)) sub_rows <- unique(sapply(row_parts, `[`, 2)) n_groups <- nlevels(groups) n_subrows <- length(sub_rows) n_cols <- ncol(dfs) # 构建3D数组 array_result <- array( data = t(matrix(dfs, nrow = n_subrows, ncol = n_groups * n_cols)), dim = c(n_subrows, n_cols, n_groups), dimnames = list( rows = sub_rows, columns = colnames(dfs), levels = levels(groups) ) ) # 可选:将3D数组转换为和期望输出一致的列表格式 array_to_list <- lapply(seq(dim(array_result)[3]), function(i) { mat <- array_result[, , i] colnames(mat) <- gsub(" ", "X", colnames(mat)) mat }) names(array_to_list) <- c("a", "b", "c")
代码说明
- 动态适配:通过
strsplit自动识别分组数量,不管有多少个第三维度层级,都能完成拆分,无需手动修改代码 - 递归兼容:只要行名遵循
分组:子项的格式,就能自动处理任意数量的分组 - 格式匹配:通过
gsub替换列名空格为X,完全对齐期望输出的格式
内容的提问来源于stack exchange,提问作者GSA
相关产品推荐
相关产品推荐

