You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:45:01