I have a file of size 800MB that I would like to iterate through and find which taxonID belongs to which kingdom. Each row has a parentNameUsageID which points to its next parent. I recurse until I find next parent whose taxonRank is kingdom. The file over 2M records which makes it resource intensive. I have a working script that does what I need but I create a dictionary so I can easily access the attributes and once the whole dictionary is updated with the new kingdom field, I write it to a file. Is there is a better way to do it, like read -> update -> write each row to a new file without waiting for the whole thing to finish?
Also, Can we do it in a better way so it doesnot use as much resources and goes faster than 2 rows in a mins (that's the current speed)? Each recursion opens the file again. If I dont, it only iterates through part of the file and not the whole file.
Sample Data file cab be downloaded from here - 840 MB
Code:
import csv
import time
import io
file_name = "Taxon.tsv"
def getKingdomName(parentID):
with open(file_name, "r", encoding="utf-8") as file:
tfr = csv.DictReader(file, delimiter="\t")
for t in tfr:
if t["dwc:taxonID"] == parentID:
# print("Found", t["dwc:taxonID"])
if t["dwc:taxonRank"] == 'kingdom':
# print("kingdom name: ", t["dwc:scientificName"])
return t["dwc:scientificName"]
else:
# print("No kingdom match. Calling getKingdomName with", t["dwc:parentNameUsageID"])
return getKingdomName(t["dwc:parentNameUsageID"])
else:
pass
with open(file_name, "r", encoding="utf-8") as file:
taxon_file = csv.DictReader(file, delimiter="\t")
new_taxon_file = None
print("start:", time.strftime("%H:%M:%S", time.localtime()))
for line in taxon_file:
# print(line)
kingdomName = getKingdomName(line["dwc:parentNameUsageID"])
line["dwc:kingdom"] = kingdomName
print(line)
memory_file = io.StringIO()
with open('Taxon-out.tsv', "w", encoding="utf-8", newline='') as output:
writer = csv.DictWriter(output, fieldnames=taxon_file.fieldnames, delimiter="\t")
for row in taxon_file:
writer.writerow(row)
print("end:", time.strftime("%H:%M:%S", time.localtime()))
``