问题
This question is related to: How to get taxonomic specific ids for kingdom, phylum, class, order, family, genus and species from taxid?
The solution given there works but I would like to have the names for each taxonomic ids for defined ranks. I have found this on ete3 which can do the job:
names = ncbi.get_taxid_translator(lineage)
print [names[taxid] for taxid in lineage]
but not being python programmer, I am failing to incorporate this into the code given in the link above. Here is what I have tried:
import csv
from ete3 import NCBITaxa
ncbi = NCBITaxa()
def get_desired_ranks(taxid, desired_ranks):
lineage = ncbi.get_lineage(taxid)
print lineage
#[1, 131567, 2157, 28890, 183925, 2158, 2159, 2160, 2162, 1204725]
names = ncbi.get_taxid_translator(lineage)
print names
#{1: u'root', 2157: u'Archaea', 2158: u'Methanobacteriales', 2159: u'Methanobacteriaceae', 2160: u'Methanobacterium', 2162: u'Methanobacterium formicicum', 183925: u'Methanobacteria', 28890: u'Euryarchaeota', 131567: u'cellular organisms', 1204725: u'Methanobacterium formicicum DSM 3637'}
lineage2ranks = ncbi.get_rank(names)
print lineage2ranks
#{1: u'no rank', 2157: u'superkingdom', 2158: u'order', 2159: u'family', 2160: u'genus', 2162: u'species', 183925: u'class', 28890: u'phylum', 131567: u'no rank', 1204725: u'no rank'}
ranks2lineage = dict((rank,taxid) for (taxid, rank) in lineage2ranks.items())
print ranks2lineage
return{'{}_id'.format(rank): ranks2lineage.get(rank, '<not present>') for rank in desired_ranks}
def main(taxids, desired_ranks, path):
with open(path, 'w') as csvfile:
fieldnames = ['{}_id'.format(rank) for rank in desired_ranks]
writer = csv.DictWriter(csvfile, delimiter='\t', fieldnames=fieldnames)
writer.writeheader()
for taxid in taxids:
writer.writerow(get_desired_ranks(taxid, desired_ranks))
if __name__ == '__main__':
taxids = [1204725, 2162, 1300163, 420247]
desired_ranks = ['kingdom', 'phylum', 'class', 'order', 'family', 'genus', 'species']
path = 'taxids.csv'
main(taxids, desired_ranks, path)
Many thanks for any help you could provide.
回答1:
Let's leave your taxids
as they are.
taxids = [1204725, 2162, 1300163, 420247]
Then call get_desired_ranks
for each individual taxid
.
for taxid in taxids:
ranks = get_desired_ranks(taxid, desired_ranks)
Now call ncbi.get_taxid_translator
for each key
(rank) in ranks
and print
the output:
for taxid in taxids:
print(ncbi.get_taxid_translator([taxid]))
ranks = get_desired_ranks(taxid, desired_ranks)
for key, rank in ranks.items():
if rank != '<not present>':
print(ncbi.get_taxid_translator([rank]))
Output
{1204725: 'Methanobacterium formicicum DSM 3637'}
{183925: 'Methanobacteria'}
{2159: 'Methanobacteriaceae'}
{2160: 'Methanobacterium'}
{28890: 'Euryarchaeota'}
{2162: 'Methanobacterium formicicum'}
{2158: 'Methanobacteriales'}
{2162: 'Methanobacterium formicicum'}
[...]
{420247: 'Methanobrevibacter smithii ATCC 35061'}
{183925: 'Methanobacteria'}
{2159: 'Methanobacteriaceae'}
{2172: 'Methanobrevibacter'}
{28890: 'Euryarchaeota'}
{2173: 'Methanobrevibacter smithii'}
{2158: 'Methanobacteriales'}
Complete code with improved output
import csv
from ete3 import NCBITaxa
ncbi = NCBITaxa()
def get_desired_ranks(taxid, desired_ranks):
lineage = ncbi.get_lineage(taxid)
names = ncbi.get_taxid_translator(lineage)
lineage2ranks = ncbi.get_rank(names)
ranks2lineage = dict((rank,taxid) for (taxid, rank) in lineage2ranks.items())
return{'{}_id'.format(rank): ranks2lineage.get(rank, '<not present>') for rank in desired_ranks}
if __name__ == '__main__':
taxids = [1204725, 2162, 1300163, 420247]
desired_ranks = ['kingdom', 'phylum', 'class', 'order', 'family', 'genus', 'species']
for taxid in taxids:
print(list(ncbi.get_taxid_translator([taxid]).values())[0])
ranks = get_desired_ranks(taxid, desired_ranks)
for key, rank in ranks.items():
if rank != '<not present>':
print(key + ': ' + list(ncbi.get_taxid_translator([rank]).values())[0])
print('=' * 60)
If you want to have a tab-separated output you can concatenate the strings with \t
or just add all results to a list
and join
with \t
.
In the snippet below, the results are stored in a list
called results
which contains another list which stores your fields (original ID, kingdom, etc.). In each loop the results are added to the last entry (results[-1]
).
if __name__ == '__main__':
taxids = [1204725, 2162, 1300163, 420247]
desired_ranks = ['kingdom', 'phylum', 'class', 'order', 'family', 'genus', 'species']
results = list()
for taxid in taxids:
results.append(list())
results[-1].append(str(taxid))
ranks = get_desired_ranks(taxid, desired_ranks)
for key, rank in ranks.items():
if rank != '<not present>':
results[-1].append(list(ncbi.get_taxid_translator([rank]).values())[0])
else:
results[-1].append(rank)
#generate the header
header = ['Original_query_taxid']
header.extend(desired_ranks)
print('\t'.join(header))
#print the results
for result in results:
print('\t'.join(result))
Output
Original_query_taxid kingdom phylum class order family genus species
1204725 Methanobacterium formicicum Methanobacteriaceae Euryarchaeota
Methanobacteria Methanobacteriales Methanobacterium <not present>
2162 Methanobacterium formicicum Methanobacteriaceae Euryarchaeota
Methanobacteria Methanobacteriales Methanobacterium <not present>
1300163 Methanobacterium formicicum Methanobacteriaceae Euryarchaeota
Methanobacteria Methanobacteriales Methanobacterium <not present>
420247 Methanobrevibacter smithii Methanobacteriaceae Euryarchaeota
Methanobacteria Methanobacteriales Methanobrevibacter <not present>
回答2:
I do not have enough reputation to comment the Maximilian Peters answer. I tried his code and it worked, but the information was not displayed in the order of desired_ranks = ['kingdom', 'phylum', 'class', 'order', 'family', 'genus', 'species']
.
To get the information in the right column, with superkingdom information, use:
import csv
from ete3 import NCBITaxa
ncbi = NCBITaxa()
def get_desired_ranks(taxid, desired_ranks):
lineage = ncbi.get_lineage(taxid)
names = ncbi.get_taxid_translator(lineage)
lineage2ranks = ncbi.get_rank(names)
ranks2lineage = dict((rank,taxid) for (taxid, rank) in lineage2ranks.items())
return{'{}_id'.format(rank): ranks2lineage.get(rank, '<not present>') for rank in desired_ranks}
if __name__ == '__main__':
taxids = [1204725, 2162, 1300163, 420247]
desired_ranks = ['superkingdom', 'kingdom', 'phylum', 'class', 'order', 'family', 'genus', 'species']
results = list()
for taxid in taxids:
results.append(list())
results[-1].append(str(taxid))
ranks = get_desired_ranks(taxid, desired_ranks)
for key, rank in ranks.items():
if rank != '<not present>':
results[-1].append(list(ncbi.get_taxid_translator([rank]).values())[0])
else:
results[-1].append(rank)
#generate the header
header = ['Original_query_taxid']
header.extend(desired_ranks)
print('\t'.join(header))
#print the results
for result in results:
print('\t'.join([result[i] for i in [0, 2, 5, 7, 4, 6, 3, 8, 1]]))
Output:
Original_query_taxid superkingdom kingdom phylum class order family genus species
1204725 Archaea <not present> Euryarchaeota Methanobacteria Methanobacteriales Methanobacteriaceae Methanobacterium Methanobacterium formicicum
2162 Archaea <not present> Euryarchaeota Methanobacteria Methanobacteriales Methanobacteriaceae Methanobacterium Methanobacterium formicicum
1300163 Archaea <not present> Euryarchaeota Methanobacteria Methanobacteriales Methanobacteriaceae Methanobacterium Methanobacterium formicicum
420247 Archaea <not present> Euryarchaeota Methanobacteria Methanobacteriales Methanobacteriaceae Methanobrevibacter Methanobrevibacter smithii
This output matches the NCBI information, e.g. https://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?id=1204725.
来源:https://stackoverflow.com/questions/43867631/how-can-i-get-taxonomic-rank-names-from-taxid