Cursus
Dingen tellen klinkt simpel totdat de uitkomsten net niet kloppen—of flink afwijken. Ik heb frequentiecontroles gezien met herhaalde aanroepen van list.count() of verkeerd gebruikte pandas-methoden die stilletjes missende waarden overslaan. Gevolg: trage code en verkeerde aantallen. De oplossing is het juiste gereedschap voor de klus: collections.Counter voor frequentiemaps, de ingebouwde count() voor snelle single-value queries, en pandas’ value_counts() als je in een DataFrame werkt.
Wat is Counter en hoe werkt het
collections.Counter is een dictionary-subklasse om hashbare objecten te turven (een multiset). Je kunt een Counter opbouwen uit een iterable of een mapping. Missende keys geven standaard 0; tellingen kun je verhogen of verlagen; en meerdere handige methoden maken veelvoorkomende taken eenvoudig.
from collections import Counter
# From an iterable (one pass over the data)
nyc_eatery_types = [
"Mobile Food Truck", "Food Cart", "Snack Bar", "Restaurant", "Food Cart",
"Restaurant", "Mobile Food Truck", "Snack Bar", "Mobile Food Truck"
]
eatery_type_counts = Counter(nyc_eatery_types)
print(eatery_type_counts) # dict-like view
print(eatery_type_counts["Restaurant"]) # missing keys return 0 instead of KeyError
print(eatery_type_counts["Kiosk"])
Counter({'Mobile Food Truck': 3, 'Food Cart': 2, 'Snack Bar': 2, 'Restaurant': 2})
2
0
Vertrouw niet op de iteratievolgorde van een Counter. Wanneer je een gerangschikte weergave nodig hebt, gebruik je most_common().
Vind de meest voorkomende waarden met most_common()
Counter.most_common(n) retourneert een lijst met (item, count)-paren in aflopende volgorde van telling. Geef n op om te beperken, of laat het weg om alle paren te krijgen.
top_3 = eatery_type_counts.most_common(3)
print(top_3)
[('Mobile Food Truck', 3), ('Food Cart', 2), ('Snack Bar', 2)]
Gebruik dit voor frequentie-analyses, leaderboards of snelle sanity checks op categorische data.
Meer doen met Counter
tellingen bijwerken en aftrekken
Bedrijfsdata verandert. update() telt erbij op, terwijl subtract() vermindert. Beide accepteren iterables of mappings.
new_permits = ["Restaurant", "Food Cart", "Restaurant"]
eatery_type_counts.update(new_permits) # add 1 for each occurrence
print(eatery_type_counts)
closures = {"Snack Bar": 1}
eatery_type_counts.subtract(closures) # reduce counts (can go negative)
print(eatery_type_counts)
Counter({'Mobile Food Truck': 3, 'Restaurant': 4, 'Food Cart': 3, 'Snack Bar': 2})
Counter({'Restaurant': 4, 'Mobile Food Truck': 3, 'Food Cart': 3, 'Snack Bar': 1})
Als een telling naar 0 of lager gaat, negeren methoden zoals elements() en most_common() deze. Gebruik del counter[key] om een key volledig te verwijderen.
totalen en top-N berekenen
Vanaf Python 3.10 geeft Counter.total() de som van alle tellingen. Handig wanneer je proporties of aandelen nodig hebt.
total_permits = eatery_type_counts.total()
for eatery, count in eatery_type_counts.most_common(3):
share = count / total_permits
print(f"{eatery}: {count} ({share:.1%})")
reeksen herbouwen met elements()
elements() levert elk element zo vaak als de telling aangeeft. De volgorde is willekeurig.
expanded = list(eatery_type_counts.elements())
print(len(expanded), "items reconstructed from counts")
rekenkundige en set-achtige operaties gebruiken
Je kunt counters combineren met rekenkundige en min/max-achtige operaties. Resultaten laten nullen en negatieve tellingen weg.
from collections import Counter
a = Counter({"Food Cart": 5, "Restaurant": 2})
b = Counter({"Food Cart": 3, "Snack Bar": 4})
print(a + b) # add counts
print(a - b) # subtract (keeps positives only)
print(a & b) # intersection: min of counts
print(a | b) # union: max of counts
Counter({'Food Cart': 8, 'Snack Bar': 4, 'Restaurant': 2})
Counter({'Food Cart': 2, 'Restaurant': 2})
Counter({'Food Cart': 3})
Counter({'Food Cart': 5, 'Snack Bar': 4, 'Restaurant': 2})
Wanneer gebruik je list.count(), Counter of pandas
Kies het eenvoudigste hulpmiddel dat aan je eisen en prestatiegrenzen voldoet.
single-value checks met count()
Gebruik de ingebouwde count() wanneer je alleen wilt weten hoe vaak één waarde voorkomt in een reeks of een niet-overlappende substring-telling in een string.
numbers = [1, 2, 2, 3, 2]
print(numbers.count(2)) # 3
word = "banana"
print(word.count("a")) # 3
text = "aaa"
print(text.count("aa")) # 1: non-overlapping matches only
print("cat".count("")) # 4: empty string counts len(s)+1 positions
Wees voorzichtig met booleans en integers: True == 1 en False == 0. Dit kan tellingen opblazen als je typen door elkaar gebruikt.
mixed = [1, True, 0, False, True]
print(mixed.count(1)) # 3 (counts 1 and True)
print(mixed.count(0)) # 2 (counts 0 and False)
Vermijd herhaald count() aanroepen binnen lussen op grote data; elke aanroep scant de hele reeks.
# Inefficient: O(n^2) for large lists
# freq = {x: numbers.count(x) for x in numbers}
# Efficient: one pass
from collections import Counter
freq = Counter(numbers)
meerdere frequenties met Counter
Als je tellingen voor veel unieke waarden nodig hebt, bouw dan één keer een Counter en bevraag die naar behoefte. Het is duidelijk, snel en hiervoor ontworpen.
tabeldata met pandas
In pandas berekenen DataFrame.count() en Series.count() niet-missende tellingen. Voor een frequentietabel van waarden gebruik je Series.value_counts().
import pandas as pd
df = pd.DataFrame({
"line": ["A", "A", "B", None, "B", "B"],
"ridership": [100, None, 120, 130, None, 150],
})
print(df["line"].count()) # 5 (non-missing)
print(df["line"].value_counts()) # value frequencies
# For full row count, use len(df), not df.count()
print(len(df)) # 6
Valideren en opschonen van data met Counter
Voor analyse check ik categorische consistentie, onverwachte waarden en duplicaten. Counter maakt deze controles snel en herhaalbaar.
from collections import Counter
# Example: validate allowed categories
allowed_types = {"Mobile Food Truck", "Food Cart", "Snack Bar", "Restaurant"}
type_counts = Counter(nyc_eatery_types)
unexpected = {t: c for t, c in type_counts.items() if t not in allowed_types}
if unexpected:
print("Unexpected categories found:", unexpected)
# Example: flag duplicates (e.g., station IDs appearing more than once)
station_ids = ["ST-001", "ST-002", "ST-003", "ST-002", "ST-004", "ST-002"]
dup_counts = Counter(station_ids)
duplicates = [sid for sid, c in dup_counts.items() if c > 1]
print("Duplicate station IDs:", duplicates)
Praktische notities en veelvoorkomende valkuilen
Deze details besparen tijd en voorkomen subtiele bugs.
Counteris dict-achtig: missende keys geven 0; gebruikdel counter[key]om entries te verwijderen. Vermijd het opslaan van nullen tenzij je ze tijdelijk nodig hebt.
- Vertrouw niet op iteratievolgorde. Gebruik
most_common()voor gerangschikte output.
str.count()telt niet-overlappende matches. Voor overlappende substring-tellingen gebruik jere.finditer().
- Vermijd herhaalde aanroepen van
list.count()op dezelfde grote reeks. Bouw in plaats daarvan éénCounter.
- In pandas is
.count()voor niet-missende tellingen; gebruik.value_counts()voor waarde-frequenties.
Minimale patronen waar ik op vertrouw
Dit zijn de snippets die ik het vaakst gebruik in productie en onderwijs.
- One-pass frequentiemap:
Counter(iterable)
- Top-N categorieën:
Counter(data).most_common(n)
- Incrementele updates:
counter.update(batch)ofcounter.subtract(batch)
- Single-value check:
sequence.count(x)(vermijd in lussen)
- Tabel-frequenties:
df["col"].value_counts()(nietdf.count())
Conclusie
collections.Counter is het juiste hulpmiddel om meerdere waarden snel en duidelijk te tellen. Gebruik de ingebouwde count() voor eenmalige checks, Counter voor frequentiemaps en top-N-analyses, en Series.value_counts() wanneer je met pandas werkt. Let op randgevallen bij string-telling, de gelijkwaardigheid van booleans en integers, en het verschil tussen niet-missende tellingen en waarde-frequenties. Met deze patronen zijn je tellingen zowel snel als correct.
