4
$\begingroup$

I have a file contain multiple sequence, and I want to separate them by "gene:" into different file. example:

example.fa

>KQK21959
ATGGTGCTCGACCCCGTCGTCGGGGGCTCGGCCTCCCGCAAGGTCGAGCCCCTAACCCTA

>KQK14546
ATGCCTCCGCCGGACGCGGCCACCTACGCTCCCACGCTGCCAATGGCGACGTACCTCCCA

How to get results like this? One sequence per file, and after > is gene id, not cds id

KQK21959.fa

>KQK21959
ATGGTGCTCGACCCCGTCGTCGGGGGCTCGGCCTCCCGCAAGGTCGAGCCCCTAACCCTA

KQK14546.fa

>KQK14546
ATGCCTCCGCCGGACGCGGCCACCTACGCTCCCACGCTGCCAATGGCGACGTACCTCCCA
$\endgroup$

6 Answers 6

3
$\begingroup$

A simple Biopython solution:

from Bio import SeqIO

for record in SeqIO.parse("example.fa", "fasta"):
    SeqIO.write(record, record.id + ".fa", "fasta")

Note, if you have multiple sequences with the same id, only the last sequence will be kept in the final output files

$\endgroup$
1
  • $\begingroup$ Thank you! It works excellent. $\endgroup$
    – user8692
    Commented May 15, 2020 at 3:06
3
$\begingroup$

There's an app for that! The exonerate package (see here) includes a nice fastaexplode command that does exactly what you're looking for and will be much, much faster than anything we give you here since it is written in C and not a scripting language. Just install exonerate (you can do that with sudo apt install exonerate on Debian-based systems) and then:

fastaexplode file.fa

This will create these two files (file.fa is the original input file from your question):

$ ls
file.fa  KQK14546.fa  KQK21959.fa
$\endgroup$
2
$\begingroup$

This can also be done using awk. This is harder to read, but probably faster than python:

awk 'sub(/^>/,""){
        FILE=$0".fa"; 
    print ">"$0 >FILE; 
        next
    }{print > FILE}' file.fa. 

This will define a new output file FILE at each header line, whose filename is the header minus the > character, suffixed with .fa. And all lines in the file are appended to the current output file.

EDIT: Changed to a faster version found on: https://crashcourse.housegordon.org/split-fasta-files.html#using-awk-instead-of-csplitsed

$\endgroup$
0
2
$\begingroup$

That really depends on the tools you are using. If anything will do you can use the following python snippet.

If you know that each sequence is on a single line and your file isnt gigantic use this

EDIT

Updated so the file isn't read to memory at once to address @terdon point. Although, the above solutions are probably much better.

with open( "seqs.fasta" ) as f:
    out = ""
    
    for line in f:
        if not line.strip(): continue 
        if line.startswith( ">" ):
            if not type( out ) == str: out.close()
            gene = line[1:].strip().split()[0]
            out = open( f"{gene}.fa", "w" )
            out.write( line )
            continue 
        out.write( line.strip() )
    
$\endgroup$
0
2
$\begingroup$

This worked for me today:

# Load required packages
BiocManager::install("Biostrings")

library(Biostrings)

# Read the multi-genome FASTA file
multi_genome_fasta <- readDNAStringSet("*.fasta")

# Extract individual genomes and save as separate FASTA files
for (i in 1:length(multi_genome_fasta)) {
    header <- names(multi_genome_fasta)[i]
    sequence <- as.character(multi_genome_fasta[i])
    
    # Combine header and sequence
    combined_data <- paste(">", header, sequence)
    
    # Save the combined data as a separate FASTA file
    file_name <- paste0(header, ".fasta")
    writeLines(combined_data, file_name)
    
    cat("Saved", header, "as", file_name, "\n")
}

cat("Separation completed.\n")
$\endgroup$
2
$\begingroup$

There are many ways to do it. Here is one way to do in Python.

import os

with open("input.fasta") as f:
    for line in f:
        if line.startswith('>'):
            record_name = line.lstrip(">")
            outfilename = f"{(record_name.rstrip())}.fasta"
            if not os.path.exists(outfilename):
                out = open(outfilename, 'w+')       
            else:
                print('File already exists!')
        out.write(line)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.