如何在R中合并不同目录下的NEXUS格式序列文件?
问题
我有一个名为simulations的文件夹,其中包含100个子文件夹,每个子文件夹内存放着模拟结果。每个子文件夹中有4个独立文件:seq[1].nex、seq[2].nex、seq[3].nex和seq[4].nex。
文件格式示例(seq[1].nex):
#NEXUS Begin data; Dimensions ntax=5 nchar=55; Format datatype=Standard symbols="01" missing=? gap=-; Matrix L1 1100110010010100010110000110000010000100001011010010110 L2 1101110110011010010000010111000010010000001001010110110 L3 0111111100010100010011000001100011010100010010110011110 L4 1101110110011010010000010111000010010000001001010110110 L5 1101110100110100010110010110001010010100001011010110100 ; End;
seq[2].nex示例(行数和seq[1].nex一致,但每行序列长度不同):
#NEXUS Begin data; Dimensions ntax=5 nchar=20; Format datatype=Standard symbols="012" missing=? gap=-; Matrix L1 10000012202011210001 L2 10002112212010210012 L3 10002112212210220022 L4 10002112212010220012 L5 10001112212010222012 ; End;
需求:
- 为每个子文件夹合并这4个文件为
seq.nex - 以
seq[1].nex为基础,将seq[2]-seq[4]的对应行序列追加到seq[1]对应行的末尾 - 合并后的文件保留
seq[1].nex的头部(#NEXUS到Matrix部分),仅更新序列行,示例输出如下:
#NEXUS Begin data; Dimensions ntax=5 nchar=55; Format datatype=Standard symbols="01" missing=? gap=-; Matrix L1 110011001001010001011000011000001000010000101101001011010000012202011210001 L2 110111011001101001000001011100001001000000100101011011010002112212010210012 L3 011111110001010001001100000110001101010001001011001111010002112212210220022 L4 110111011001101001000001011100001001000000100101011011010002112212010220012 L5 110111010011010001011001011000101001010000101101011010010001112212010222012 ; End;
请问能否用R实现批量处理这100个子文件夹的需求?
解决方案
完全可以用R实现,以下是具体代码步骤:
步骤1:定义单个文件夹的处理函数
该函数读取指定文件夹内的4个seq文件,合并序列后生成seq.nex:
process_folder <- function(folder_path) { # 定义要读取的文件路径列表 file_list <- file.path(folder_path, c("seq[1].nex", "seq[2].nex", "seq[3].nex", "seq[4].nex")) # 读取每个文件,提取Matrix块内的序列行 seq_data_list <- lapply(file_list, function(file) { lines <- readLines(file) # 定位Matrix块的起始和结束行 matrix_start <- which(grepl("^Matrix", lines)) + 1 matrix_end <- which(grepl("^;", lines)) - 1 # 提取并清洗序列行 seq_lines <- trimws(lines[matrix_start:matrix_end]) # 分割ID和序列,返回数据框 data.frame( id = sapply(strsplit(seq_lines, "\\s+"), `[`, 1), seq = sapply(strsplit(seq_lines, "\\s+"), `[`, 2), stringsAsFactors = FALSE ) }) # 合并所有序列:以第一个文件为基础,依次追加后续文件的对应序列 merged_seq <- seq_data_list[[1]] for (i in 2:length(seq_data_list)) { merged_seq$seq <- paste0(merged_seq$seq, seq_data_list[[i]]$seq) } # 读取第一个文件的头部和尾部内容,保留原格式 first_file_lines <- readLines(file_list[1]) header_end <- which(grepl("^Matrix", first_file_lines)) footer_start <- which(grepl("^;", first_file_lines)) header <- first_file_lines[1:header_end] footer <- first_file_lines[footer_start:length(first_file_lines)] # 拼接合并后的完整内容 merged_lines <- c( header, paste0(merged_seq$id, " ", merged_seq$seq), footer ) # 写入输出文件 writeLines(merged_lines, file.path(folder_path, "seq.nex")) # 打印处理状态 cat(sprintf("已完成文件夹处理:%s\n", folder_path)) }
步骤2:批量处理所有子文件夹
自动遍历simulations下的所有子文件夹,逐个调用处理函数:
# 设置主文件夹路径 main_folder <- "simulations" # 获取所有子文件夹路径 sub_folders <- list.dirs(main_folder, recursive = FALSE) # 批量处理 for (folder in sub_folders) { process_folder(folder) }
代码说明
- 精准定位NEXUS文件中的
Matrix块,避免干扰其他内容 - 按ID匹配序列行,保证对应行的序列正确追加
- 完全保留原文件的头部格式和尾部结构,输出文件符合NEXUS规范
- 自动遍历所有子文件夹,无需手动逐个操作
内容的提问来源于stack exchange,提问作者Namenlos
相关产品推荐
相关产品推荐

