如何用for函数按行名拆分含2850个变量的DataFrame?
问题
我有一个包含2850个变量的DataFrame,行名示例为K_1、K_1_A……K_1_AC、K_2、K_2_A……K_95_AC,每组以K_i开头的行名共30个,总计95组(95×30=2850)。我希望将DataFrame按行名拆分为95个子集(L1到L95,每个子集对应一组K_i开头的行),尝试了以下两个for循环版本,但均无法正常运行,请求解决方法:
版本1代码
for (i in 1:95) { sapply(c("K_i", "K_i_A", "K_i_B", "K_i_C", "K_i_D", "K_i_E", "K_i_F", "K_i_G", "K_i_H", "K_i_I", "K_i_J", "K_i_K", "K_i_L", "K_i_M", "K_i_N", "K_i_O", "K_i_P", "K_i_Q", "K_i_R", "K_i_S", "K_i_T", "K_i_U", "K_i_V", "K_i_W", "K_i_X", "K_i_Y", "K_i_Z", "K_i_AA", "K_i_AB", "K_i_AC"), function(x) meaning[startswWith(names(meaning),x)] simplify = FALSE}
版本2代码
group_names <- paste0("L", 1:95) num_rownames_per_group <- 30 split_df_list <- split(meaning, rep(group_names, each = num_rownames_per_group)) for(i in seq_along(split_df_list)){ group_names <- names(split_df_list)[i] print(paste("#", group_names))`your text` print(split_df_list[[i]]) cat("\n") }
解决方法
两个版本的问题分析
版本1问题点
- 字符串未动态拼接:
"K_i"是固定文本,不会随循环变量i变化,无法匹配对应组的行名 - 函数名拼写错误:
startswWith应为startswith - 语法错误:
sapply的simplify = FALSE参数位置错误,且循环内未将结果赋值给变量,无法保存子集 - 逻辑冗余:无需手动列出所有后缀,直接通过前缀匹配即可筛选组内所有行
版本2问题点
- 依赖行顺序:假设行严格按
K_1组30行、K_2组30行……排列,若行顺序混乱则分组错误 - 语法错误:
print(paste("#", group_names))后多余的your text反引号导致代码报错
正确实现方案
方案1:按行名前缀分组(通用可靠)
通过正则提取行名中的组编号,再按编号分组,不受行顺序影响:
# 从行名中提取组编号(例:从K_1、K_1_A中提取数字1) group_ids <- sub("^K_(\\d+).*", "\\1", rownames(meaning)) # 生成L1-L95的组名 group_names <- paste0("L", group_ids) # 按组名拆分DataFrame split_df_list <- split(meaning, group_names) # 遍历输出每个子集(可选) for(i in seq_along(split_df_list)){ current_name <- names(split_df_list)[i] cat(paste0("# ", current_name, "\n")) print(split_df_list[[i]]) cat("\n") }
方案2:固定行顺序下的修正版
若确认行严格按每组30行排列,直接修正版本2的语法错误即可:
group_names <- paste0("L", 1:95) num_rownames_per_group <- 30 split_df_list <- split(meaning, rep(group_names, each = num_rownames_per_group)) for(i in seq_along(split_df_list)){ current_name <- names(split_df_list)[i] print(paste("#", current_name)) print(split_df_list[[i]]) cat("\n") }
说明
- 方案1适用性更强,无论行顺序如何,只要行名符合
K_i开头的规则就能正确分组 - 拆分后的
split_df_list为列表,可通过split_df_list[["L1"]]直接调用对应子集
内容的提问来源于stack exchange,提问作者Haejin Kim
相关产品推荐
相关产品推荐

