如何用R语言迭代列表并生成带分组变量的数据框?
问题
需要从大量复杂的XML Esri Workspace文件中提取表名、分组变量、变量名及变量值,当前在迭代分组变量列表时,无法实现分组变量与变量名、值的对应重复。以表名列表(table 1, table 2)、变量名列表(A, B)为例,期望生成包含对应关系的数据框,但现有for循环代码未能得到预期结果。
尝试代码
tableNames <- c(seq(1:2)) varNames <- c("A", "B") results <- cbind(rep(0, length(tableNames) + length(varNames)), 0) for(i in seq_along(tableNames)){ results3[i, 1] <- tableNames[i] for(j in seq_along(varNames)){ results3[i, 2] <- varNames[j] } } results
错误结果
....[,1] [,2] [1,] "1" "B" [2,] "2" "B" [3,] "0" "0" [4,] "0" "0"
预期结果
....[,1] [,2] [1,] "1" "A" [2,] "1" "B" [3,] "2" "A" [4,] "2" "B"
解决方法
方法1:使用expand.grid生成笛卡尔积(推荐)
R内置的expand.grid可直接生成多个向量的笛卡尔积,完美匹配需求,代码简洁高效:
tableNames <- c(1:2) varNames <- c("A", "B") # 生成对应关系的数据框 result_df <- expand.grid(tableName = tableNames, varName = varNames) # 按表名排序以匹配预期结果顺序 result_df <- result_df[order(result_df$tableName), ] rownames(result_df) <- NULL # 重置行名 print(result_df)
输出:
tableName varName 1 1 A 2 1 B 3 2 A 4 2 B
方法2:用tidyverse的crossing适配多层分组
如果需要处理更复杂的多层分组场景,tidyverse包的crossing函数更灵活,支持任意长度的分组变量组合:
library(tidyverse) tableNames <- c(1:2) varNames <- c("A", "B") values <- c(1,2) # 示例:加入值列表 # 生成三层变量的所有组合 result_df <- crossing(tableName = tableNames, varName = varNames, value = values) print(result_df)
该方法可轻松扩展到更多层级的分组需求。
方法3:修正原有for循环逻辑
若坚持使用for循环,需修正结果矩阵的初始化和行索引逻辑:
tableNames <- c(1:2) varNames <- c("A", "B") # 初始化正确长度的结果矩阵(表数×变量数行) results <- matrix(0, nrow = length(tableNames)*length(varNames), ncol = 2) row_idx <- 1 for(i in seq_along(tableNames)){ for(j in seq_along(varNames)){ results[row_idx, 1] <- tableNames[i] results[row_idx, 2] <- varNames[j] row_idx <- row_idx + 1 # 每次循环后更新行索引 } } print(results)
运行后将得到与预期一致的结果。
内容的提问来源于stack exchange,提问作者anagler
相关产品推荐
相关产品推荐

