| name | python-bio-dictionaries |
| description | Use Python dict/defaultdict/Counter/set to translate codons, count k-mers, group genes by chromosome, and compare gene lists (union/intersection). Use when translating DNA, counting k-mers, or comparing gene sets. |
| tool_type | python |
| primary_tool | Python |
Dictionaries and Sets in Bioinformatics
When to Use
- Translating DNA/RNA to protein via a codon lookup table (
GENETIC_CODE dict).
- Counting nucleotides, k-mers, or codons in a sequence (
Counter).
- Grouping records by a key without manual
if key not in d boilerplate (defaultdict).
- Comparing gene lists between conditions, studies, or orthologous species (set algebra:
&, |, -, ^).
- Building a small in-memory gene/variant annotation database keyed by ID, or deduplicating a list of sequences/IDs.
Version Compatibility
Pure Python stdlib (dict, set, collections.defaultdict, collections.Counter). No version sensitivity — works unchanged on Python ≥3.8 (dict insertion order, which the examples below rely on, has been guaranteed since 3.7).
Prerequisites
- No third-party packages required — everything here is
collections from the standard library.
- Prior concepts: basic Python control flow and string slicing (
seq[i:i+3]); if working with real FASTA/annotation files, pair with biopython or bio-sequence-io-read-sequences to get sequences into strings first.
Goal: Translate a DNA coding sequence into a protein string using a codon lookup table.
Approach: Store the standard genetic code as a dict[str, str], then slice the sequence into codons and look each one up with .get() so unrecognized/ambiguous codons don't raise KeyError.
GENETIC_CODE = {
'TTT': 'F', 'TTC': 'F', 'TTA': 'L', 'TTG': 'L',
'CTT': 'L', 'CTC': 'L', 'CTA': 'L', 'CTG': 'L',
'ATT': 'I', 'ATC': 'I', 'ATA': 'I', 'ATG': 'M',
'GTT': 'V', 'GTC': 'V', 'GTA': 'V', 'GTG': 'V',
'TCT': 'S', 'TCC': 'S', 'TCA': 'S', 'TCG': 'S',
'CCT': 'P', 'CCC': 'P', 'CCA': 'P', 'CCG': 'P',
'ACT': 'T', 'ACC': 'T', 'ACA': 'T', 'ACG': 'T',
'GCT': 'A', 'GCC': , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
: , : , : , : ,
}
():
protein = []
i (, (dna) - , ):
codon = dna[i:i + ]
aa = GENETIC_CODE.get(codon, )
aa == :
protein.append(aa)
.join(protein)
cds =
(translate(cds))
Goal: Count nucleotide/k-mer frequencies and compare k-mer profiles between two sequences.
Approach: Counter is a dict subclass built for counting — it supports .most_common() and set-like arithmetic (& = min of shared counts, + = sum of counts) directly on the counts.
from collections import Counter
def kmer_counts(sequence, k=3):
"""Return a Counter of overlapping k-mers in `sequence`."""
return Counter(sequence[i:i + k] for i in range(len(sequence) - k + 1))
seq_a = "ATGATGATGCCC"
seq_b = "ATGATGGGGATG"
kmers_a = kmer_counts(seq_a)
kmers_b = kmer_counts(seq_b)
shared = kmers_a & kmers_b
combined = kmers_a + kmers_b
print(kmers_a.most_common(3))
print(dict(shared))
sequence = "ATGCGATCGATCGTAGCGATCGATCGATGCGA"
freq = {}
for nt in sequence:
freq[nt] = freq.get(nt, 0) + 1
gc_pct = (freq.get('G', 0) + freq.get('C', 0)) / len(sequence) * 100
Goal: Group genes by chromosome, then compare gene sets across studies or orthologous species.
Approach: defaultdict(list) removes the if key not in d: d[key] = [] boilerplate; set operators (&, |, -, ^) give one-line intersection/union/difference for gene-list comparisons.
from collections import defaultdict
def group_by_chromosome(gene_locations):
"""Group (gene, chrom) pairs into {chrom: [genes]}."""
by_chrom = defaultdict(list)
for gene, chrom in gene_locations:
by_chrom[chrom].append(gene)
return by_chrom
gene_locations = [("BRCA1", "chr17"), ("TP53", "chr17"), ("EGFR", "chr7"), ("MYC", "chr8")]
by_chrom = group_by_chromosome(gene_locations)
cancer_genes = {"BRCA1", "TP53", "EGFR", "MYC", "KRAS"}
dna_repair_genes = {"BRCA1", "BRCA2", "ATM", "MLH1", "TP53"}
shared = cancer_genes & dna_repair_genes
all_genes = cancer_genes | dna_repair_genes
cancer_only = cancer_genes - dna_repair_genes
exclusive = cancer_genes ^ dna_repair_genes
gene_db = {
"BRCA1": {
"chromosome": "17",
"coordinates": (43044295, 43125483),
"strand": "-",
"go_terms": ["DNA repair", ],
},
}
start, end = gene_db[][]
Pitfalls
KeyError vs get(): Direct access d["NNN"] raises KeyError on unknown codons. Use GENETIC_CODE.get(codon, 'X') to handle ambiguous bases.
- Keys must be hashable: Lists and dicts cannot be dict keys. Tuples like
("chr17", 43044295) work; lists do not.
- Iterating and modifying simultaneously: Changing dict size during iteration raises
RuntimeError. Collect changes separately, then apply.
in checks keys, not values: "ATG" in codon_table is True if "ATG" is a key. For values: "Met" in codon_table.values().
- Sets are unordered:
my_set[0] raises TypeError. Use sorted(my_set) to get ordered elements.
- Empty set:
{} creates an empty dict, not a set. Use set().
- Set elements must be hashable: Use
frozenset when you need a set of sets.
- Counter arithmetic drops non-positive counts:
Counter(a) - Counter(b) discards zero/negative results, unlike a plain dict subtraction.
See Also
bio-sequence-manipulation-codon-usage — codon usage bias and codon-optimization tables.
bio-sequence-manipulation-transcription-translation — Biopython Seq.translate() as an alternative to a manual codon dict.
bio-sequence-io-read-sequences — loading real FASTA/GenBank records into sequences to feed these patterns.
bio-population-genetics-scikit-allel-analysis — set/array operations at genome scale beyond in-memory Python dicts.