Việc đếm nghe có vẻ đơn giản cho đến khi kết quả sai lệch đôi chút—hoặc rất nhiều. Tôi từng thấy người ta kiểm tra tần suất bằng cách gọi lặp đi lặp lại list.count() hoặc dùng sai các phương thức của pandas vốn âm thầm bỏ qua giá trị thiếu. Hệ quả: mã chậm và con số sai. Cách khắc phục là dùng đúng công cụ: collections.Counter cho bản đồ tần suất, count() tích hợp sẵn cho truy vấn nhanh một giá trị, và value_counts() của pandas khi bạn làm việc trong DataFrame.
Counter là gì và hoạt động ra sao
collections.Counter là một lớp con của dictionary dùng để cộng dồn các đối tượng băm được (một multiset). Bạn có thể tạo Counter từ một iterable hoặc một mapping. Khóa thiếu mặc định là 0; số đếm có thể tăng hoặc giảm; và một số phương thức tiện lợi giúp thao tác thường gặp trở nên đơn giản.
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 viewprint(eatery_type_counts["Restaurant"])# missing keys return 0 instead of KeyErrorprint(eatery_type_counts["Kiosk"])Được hỗ trợ bởi
Counter({'Mobile Food Truck':3,'Food Cart':2,'Snack Bar':2,'Restaurant':2})20Được hỗ trợ bởi
Đừng phụ thuộc vào thứ tự lặp của một Counter. Khi cần xếp hạng, hãy dùng most_common().
Tìm giá trị xuất hiện nhiều nhất với most_common()
Counter.most_common(n) trả về danh sách các cặp (item, count) theo thứ tự giảm dần của số đếm. Truyền n để giới hạn kết quả, hoặc bỏ qua để nhận tất cả các cặp.
top_3 = eatery_type_counts.most_common(3)print(top_3)Được hỗ trợ bởi
[('Mobile Food Truck',3),('Food Cart',2),('Snack Bar',2)]Được hỗ trợ bởi
Dùng khi bạn cần phân tích tần suất, bảng xếp hạng, hoặc kiểm tra nhanh dữ liệu phân loại.
Làm được nhiều hơn với Counter
update và subtract số đếm
Dữ liệu nghiệp vụ luôn thay đổi. update() cộng thêm vào số đếm, trong khi subtract() giảm chúng. Cả hai đều nhận iterable hoặc mapping.
new_permits =["Restaurant","Food Cart","Restaurant"]
eatery_type_counts.update(new_permits)# add 1 for each occurrenceprint(eatery_type_counts)
closures ={"Snack Bar":1}
eatery_type_counts.subtract(closures)# reduce counts (can go negative)print(eatery_type_counts)Được hỗ trợ bởi
Nếu số đếm giảm về 0 hoặc âm, các phương thức như elements() và most_common() sẽ bỏ qua. Để loại bỏ hoàn toàn một khóa, dùng del counter[key].
tính tổng và top-N
Bắt đầu từ Python 3.10, Counter.total() trả về tổng của tất cả số đếm. Hữu ích khi bạn cần tỷ trọng hoặc thị phần.
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%})")Được hỗ trợ bởi
xây lại dãy với elements()
elements() trả về mỗi phần tử số lần tương ứng với số đếm của nó. Thứ tự là tùy ý.
expanded =list(eatery_type_counts.elements())print(len(expanded),"items reconstructed from counts")Được hỗ trợ bởi
dùng phép toán và thao tác kiểu tập hợp
Bạn có thể kết hợp các counter với số học và các phép kiểu min/max. Kết quả sẽ loại bỏ số đếm bằng 0 và âm.
from collections import Counter
a = Counter({"Food Cart":5,"Restaurant":2})
b = Counter({"Food Cart":3,"Snack Bar":4})print(a + b)# add countsprint(a - b)# subtract (keeps positives only)print(a & b)# intersection: min of countsprint(a | b)# union: max of countsĐược hỗ trợ bởi
Hãy chọn công cụ đơn giản nhất đáp ứng yêu cầu và ràng buộc hiệu năng của bạn.
kiểm tra một giá trị với count()
Dùng count() tích hợp khi bạn chỉ cần biết một giá trị xuất hiện bao nhiêu lần trong một dãy, hoặc đếm số lần xuất hiện không chồng lặp của một chuỗi con trong chuỗi.
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 onlyprint("cat".count(""))# 4: empty string counts len(s)+1 positionsĐược hỗ trợ bởi
Cẩn thận với boolean và số nguyên: True == 1 và False == 0. Điều này có thể làm tăng số đếm nếu bạn trộn kiểu.
mixed =[1,True,0,False,True]print(mixed.count(1))# 3 (counts 1 and True)print(mixed.count(0))# 2 (counts 0 and False)Được hỗ trợ bởi
Tránh gọi count() lặp đi lặp lại trong vòng lặp trên dữ liệu lớn; mỗi lần gọi đều quét toàn bộ dãy.
# Inefficient: O(n^2) for large lists# freq = {x: numbers.count(x) for x in numbers}# Efficient: one passfrom collections import Counter
freq = Counter(numbers)Được hỗ trợ bởi
nhiều tần suất với Counter
Khi bạn cần số đếm cho nhiều giá trị duy nhất, hãy xây một Counter một lần và truy vấn khi cần. Rõ ràng, nhanh, và được thiết kế cho trường hợp này.
dữ liệu dạng bảng với pandas
Trong pandas, DataFrame.count() và Series.count() tính số lượng không thiếu. Để có bảng tần suất của giá trị, dùng 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Được hỗ trợ bởi
Xác thực và làm sạch dữ liệu với Counter
Trước khi phân tích, tôi kiểm tra tính nhất quán của danh mục, giá trị bất ngờ, và trùng lặp. Counter giúp các kiểm tra này nhanh và lặp lại được.
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 notin 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)Được hỗ trợ bởi
Ghi chú thực tế và lỗi thường gặp
Những chi tiết này giúp tiết kiệm thời gian và tránh lỗi tinh vi.
Counter giống dict: khóa thiếu trả về 0; dùng del counter[key] để xóa mục. Tránh lưu số 0 trừ khi bạn cần tạm thời.
Đừng dựa vào thứ tự lặp. Dùng most_common() cho đầu ra có xếp hạng.
str.count() đếm các kết quả không chồng lặp. Với số lần xuất hiện chồng lặp, dùng re.finditer().
Tránh gọi list.count() lặp lại trên cùng một dãy lớn. Thay vào đó, xây một Counter.
Trong pandas, .count() dùng để đếm không thiếu; dùng .value_counts() cho tần suất giá trị.
Những mẫu tối giản tôi thường dùng
Đây là các đoạn mã tôi dùng thường xuyên trong sản xuất và giảng dạy.
Bản đồ tần suất một lượt: Counter(iterable)
Top-N danh mục: Counter(data).most_common(n)
Cập nhật gia tăng: counter.update(batch) hoặc counter.subtract(batch)
Kiểm tra một giá trị: sequence.count(x) (tránh dùng trong vòng lặp)
Tần suất dạng bảng: df["col"].value_counts() (không phải df.count())
Kết luận
collections.Counter là công cụ phù hợp để đếm nhiều giá trị một cách nhanh chóng và rõ ràng. Dùng count() tích hợp cho các kiểm tra đơn lẻ, Counter cho bản đồ tần suất và phân tích top-N, và Series.value_counts() khi bạn làm việc trong pandas. Hãy để ý các trường hợp biên khi đếm chuỗi, sự tương đương boolean–số nguyên, và khác biệt giữa đếm không thiếu và tần suất giá trị. Với những mẫu này, các con số đếm của bạn sẽ vừa nhanh vừa chính xác.
Việc đếm nghe có vẻ đơn giản cho đến khi kết quả sai lệch đôi chút—hoặc rất nhiều. Tôi từng thấy người ta kiểm tra tần suất bằng cách gọi lặp đi lặp lại
list.count()hoặc dùng sai các phương thức của pandas vốn âm thầm bỏ qua giá trị thiếu. Hệ quả: mã chậm và con số sai. Cách khắc phục là dùng đúng công cụ:collections.Countercho bản đồ tần suất,count()tích hợp sẵn cho truy vấn nhanh một giá trị, vàvalue_counts()của pandas khi bạn làm việc trong DataFrame.Counter là gì và hoạt động ra sao
collections.Counterlà một lớp con của dictionary dùng để cộng dồn các đối tượng băm được (một multiset). Bạn có thể tạoCountertừ một iterable hoặc một mapping. Khóa thiếu mặc định là 0; số đếm có thể tăng hoặc giảm; và một số phương thức tiện lợi giúp thao tác thường gặp trở nên đơn giản.Đừng phụ thuộc vào thứ tự lặp của một
Counter. Khi cần xếp hạng, hãy dùngmost_common().Tìm giá trị xuất hiện nhiều nhất với most_common()
Counter.most_common(n)trả về danh sách các cặp(item, count)theo thứ tự giảm dần của số đếm. Truyềnnđể giới hạn kết quả, hoặc bỏ qua để nhận tất cả các cặp.Dùng khi bạn cần phân tích tần suất, bảng xếp hạng, hoặc kiểm tra nhanh dữ liệu phân loại.
Làm được nhiều hơn với Counter
update và subtract số đếm
Dữ liệu nghiệp vụ luôn thay đổi.
update()cộng thêm vào số đếm, trong khisubtract()giảm chúng. Cả hai đều nhận iterable hoặc mapping.Nếu số đếm giảm về 0 hoặc âm, các phương thức như
elements()vàmost_common()sẽ bỏ qua. Để loại bỏ hoàn toàn một khóa, dùngdel counter[key].tính tổng và top-N
Bắt đầu từ Python 3.10,
Counter.total()trả về tổng của tất cả số đếm. Hữu ích khi bạn cần tỷ trọng hoặc thị phần.xây lại dãy với elements()
elements()trả về mỗi phần tử số lần tương ứng với số đếm của nó. Thứ tự là tùy ý.dùng phép toán và thao tác kiểu tập hợp
Bạn có thể kết hợp các counter với số học và các phép kiểu min/max. Kết quả sẽ loại bỏ số đếm bằng 0 và âm.
Khi nào dùng list.count(), Counter, hoặc pandas
Hãy chọn công cụ đơn giản nhất đáp ứng yêu cầu và ràng buộc hiệu năng của bạn.
kiểm tra một giá trị với count()
Dùng
count()tích hợp khi bạn chỉ cần biết một giá trị xuất hiện bao nhiêu lần trong một dãy, hoặc đếm số lần xuất hiện không chồng lặp của một chuỗi con trong chuỗi.Cẩn thận với boolean và số nguyên:
True == 1vàFalse == 0. Điều này có thể làm tăng số đếm nếu bạn trộn kiểu.Tránh gọi
count()lặp đi lặp lại trong vòng lặp trên dữ liệu lớn; mỗi lần gọi đều quét toàn bộ dãy.nhiều tần suất với Counter
Khi bạn cần số đếm cho nhiều giá trị duy nhất, hãy xây một
Countermột lần và truy vấn khi cần. Rõ ràng, nhanh, và được thiết kế cho trường hợp này.dữ liệu dạng bảng với pandas
Trong pandas,
DataFrame.count()vàSeries.count()tính số lượng không thiếu. Để có bảng tần suất của giá trị, dùngSeries.value_counts().Xác thực và làm sạch dữ liệu với Counter
Trước khi phân tích, tôi kiểm tra tính nhất quán của danh mục, giá trị bất ngờ, và trùng lặp.
Countergiúp các kiểm tra này nhanh và lặp lại được.Ghi chú thực tế và lỗi thường gặp
Những chi tiết này giúp tiết kiệm thời gian và tránh lỗi tinh vi.
Countergiống dict: khóa thiếu trả về 0; dùngdel counter[key]để xóa mục. Tránh lưu số 0 trừ khi bạn cần tạm thời.most_common()cho đầu ra có xếp hạng.str.count()đếm các kết quả không chồng lặp. Với số lần xuất hiện chồng lặp, dùngre.finditer().list.count()lặp lại trên cùng một dãy lớn. Thay vào đó, xây mộtCounter..count()dùng để đếm không thiếu; dùng.value_counts()cho tần suất giá trị.Những mẫu tối giản tôi thường dùng
Đây là các đoạn mã tôi dùng thường xuyên trong sản xuất và giảng dạy.
Counter(iterable)Counter(data).most_common(n)counter.update(batch)hoặccounter.subtract(batch)sequence.count(x)(tránh dùng trong vòng lặp)df["col"].value_counts()(không phảidf.count())Kết luận
collections.Counterlà công cụ phù hợp để đếm nhiều giá trị một cách nhanh chóng và rõ ràng. Dùngcount()tích hợp cho các kiểm tra đơn lẻ,Countercho bản đồ tần suất và phân tích top-N, vàSeries.value_counts()khi bạn làm việc trong pandas. Hãy để ý các trường hợp biên khi đếm chuỗi, sự tương đương boolean–số nguyên, và khác biệt giữa đếm không thiếu và tần suất giá trị. Với những mẫu này, các con số đếm của bạn sẽ vừa nhanh vừa chính xác.