การนับความถี่ขององค์ประกอบในลิสต์ (Frequency Counting) เป็น Operation พื้นฐานใน Data Analysis Python มีหลายวิธี ตั้งแต่ Manual ไปจนถึง Built-in Tools
วิธีที่ 1: Dictionary แบบ Manual (เข้าใจ Logic)
items = ['a', 'b', 'a', 'c', 'd', 'c', 'c']
frequency = {}
for item in items:
if item in frequency:
frequency[item] += 1
else:
frequency[item] = 1
print(frequency) # {'a': 2, 'b': 1, 'c': 3, 'd': 1}
# แสดงผลสวย
for key, value in frequency.items():
print(f"{key} -> {value}")
วิธีที่ 2: ใช้ dict.get() (สั้นกว่า)
frequency = {}
for item in items:
frequency[item] = frequency.get(item, 0) + 1
print(frequency) # {'a': 2, 'b': 1, 'c': 3, 'd': 1}
วิธีที่ 3: ใช้ collections.Counter (แนะนำ - Pythonic & Fast)
from collections import Counter
items = ['a', 'b', 'a', 'c', 'd', 'c', 'c']
frequency = Counter(items)
print(frequency) # Counter({'c': 3, 'a': 2, 'b': 1, 'd': 1})
print(dict(frequency)) # {'a': 2, 'b': 1, 'c': 3, 'd': 1}
# Most Common
print(frequency.most_common(2)) # [('c', 3), ('a', 2)]
print(frequency.most_common()) # All sorted by count
วิธีที่ 4: ใช้ list.count() (Simple แต่ช้า O(n²))
items = ['a', 'b', 'a', 'c', 'd', 'c', 'c']
frequency = {}
for item in items:
frequency[item] = items.count(item)
print(frequency) # {'a': 2, 'b': 1, 'c': 3, 'd': 1}
# ⚠️ เรียก count() ทุก Loop -> O(n²) ไม่แนะนำสำหรับ List ใหญ่
วิธีที่ 5: ใช้ defaultdict (Clean Code)
from collections import defaultdict
frequency = defaultdict(int)
for item in items:
frequency[item] += 1
print(dict(frequency)) # {'a': 2, 'b': 1, 'c': 3, 'd': 1}
Performance Comparison
import timeit
import random
import string
from collections import Counter, defaultdict
# Large List: 100,000 items
large_list = [random.choice(string.ascii_letters) for _ in range(100_000)]
methods = {
"Manual if/else": "freq={}; [freq.__setitem__(x, freq.get(x,0)+1) for x in large_list]",
"dict.get": "freq={}; [freq.__setitem__(x, freq.get(x,0)+1) for x in large_list]",
"Counter": "Counter(large_list)",
"defaultdict": "from collections import defaultdict; freq=defaultdict(int); [freq.__setitem__(x, freq[x]+1) for x in large_list]",
"count()": "freq={}; [freq.__setitem__(x, large_list.count(x)) for x in large_list]",
}
for name, code in methods.items():
# Setup code for timeit
setup = "from collections import Counter, defaultdict; import random, string; large_list = [random.choice(string.ascii_letters) for _ in range(100000)]"
time = timeit.timeit(code, setup=setup, number=10)
print(f"{name:20}: {time:.4f}s")
ผลลัพธ์ทั่วไป
Manual if/else : 0.4500s dict.get : 0.4200s Counter : 0.0800s (เร็วที่สุด - C Implementation) defaultdict : 0.3800s count() : 45.000s (ช้ามาก O(n²))
Advanced Counter Operations
from collections import Counter
c1 = Counter(a=3, b=2, c=1)
c2 = Counter(a=1, b=2, d=4)
print("c1:", c1) # Counter({'a': 3, 'b': 2, 'c': 1})
print("c2:", c2) # Counter({'d': 4, 'b': 2, 'a': 1})
# Arithmetic
print("c1 + c2:", c1 + c2) # Counter({'a': 4, 'b': 4, 'd': 4, 'c': 1})
print("c1 - c2:", c1 - c2) # Counter({'a': 2, 'c': 1}) (Only positive counts)
print("c1 & c2:", c1 & c2) # Counter({'b': 2, 'a': 1}) (Intersection: min)
print("c1 | c2:", c1 | c2) # Counter({'d': 4, 'a': 3, 'b': 2, 'c': 1}) (Union: max)
# Elements (Expand to List)
print("list(c1.elements()):", list(c1.elements())) # ['a','a','a','b','b','c']
# Subtract (In-place, allows negative)
c1.subtract(c2)
print("c1 after subtract:", c1) # Counter({'a': 2, 'c': 1, 'b': 0, 'd': -4})
การประยุกต์ใช้งานจริง
1. Word Frequency Analysis
text = "the quick brown fox jumps over the lazy dog the quick fox"
words = text.split()
word_freq = Counter(words)
print(word_freq.most_common(3)) # [('the', 3), ('quick', 2), ('fox', 2)]
2. Character Frequency (สำหรับ Cryptanalysis, Compression)
text = "hello world"
char_freq = Counter(text.replace(" ", "")) # Ignore spaces
print(char_freq.most_common()) # [('l', 3), ('o', 2), ('h', 1), ('e', 1), ('w', 1), ('r', 1), ('d', 1)]
3. Find Duplicates (จากบทความก่อนหน้า)
def find_duplicates(items):
return [item for item, count in Counter(items).items() if count > 1]
print(find_duplicates([1,2,3,2,4,3,5])) # [2, 3]
สรุป
| วิธี | Speed | Code Clarity | Features | แนะนำ |
|---|---|---|---|---|
| Manual Dict | Slow | Good | Basic | Learning |
| dict.get() | Slow | Good | Basic | Simple Scripts |
| Counter | Fastest (C) | Best | Rich (most_common, arithmetic, elements) | Production ✅ |
| defaultdict | Medium | Good | Auto-init | Custom Logic |
| list.count() | Very Slow (O(n²)) | Simple | None | Avoid |