การนับจำนวนการเกิดขึ้นของแต่ละองค์ประกอบในรายการด้วย Python’s Counter

ธุรกิจ

ใน Python สามารถหาจำนวนขององค์ประกอบทั้งหมดในรายการหรือทูเพิลได้โดยใช้ฟังก์ชันในตัว len() และจำนวนของแต่ละองค์ประกอบ (จำนวนการเกิดขึ้นของแต่ละองค์ประกอบ) สามารถรับได้โดยใช้เมธอด count() .

นอกจากนี้ คลาส Counter ของคอลเล็กชันไลบรารีมาตรฐาน Python สามารถใช้เพื่อรับองค์ประกอบตามลำดับจำนวนครั้งที่เกิดขึ้น

ในส่วนนี้เราจะพูดถึงสิ่งต่อไปนี้

  • นับจำนวนองค์ประกอบทั้งหมด:len()
  • นับจำนวนองค์ประกอบแต่ละองค์ประกอบ (จำนวนครั้งของแต่ละองค์ประกอบ):count()
  • การใช้งานcollections.Counter
  • องค์ประกอบถูกดึงมาตามลำดับความถี่ของการเกิด:most_common()
  • นับจำนวน (ประเภท) ขององค์ประกอบที่ไม่ทับซ้อนกัน (องค์ประกอบที่ไม่ซ้ำ)
  • นับจำนวนองค์ประกอบที่ตรงตามเงื่อนไข

นอกจากนี้ เป็นตัวอย่างที่เป็นรูปธรรม ต่อไปนี้จะอธิบายด้วยโค้ดตัวอย่าง

  • นับจำนวนครั้งของคำในสตริง
  • นับจำนวนการเกิดขึ้นของอักขระในสตริง

ตัวอย่างเป็นรายการ แต่การประมวลผลแบบเดียวกันสามารถทำได้ด้วยสิ่งอันดับ

นับจำนวนองค์ประกอบทั้งหมด: len()

ในการนับจำนวนองค์ประกอบทั้งหมดในรายการหรือทูเพิล ให้ใช้ฟังก์ชัน len() ในตัว

l = ['a', 'a', 'a', 'a', 'b', 'c', 'c']

print(len(l))
# 7

การนับจำนวนองค์ประกอบแต่ละองค์ประกอบ (จำนวนครั้งของแต่ละองค์ประกอบ): count() method

ในการนับจำนวนของแต่ละองค์ประกอบ (จำนวนครั้งที่เกิดขึ้นของแต่ละองค์ประกอบ) ให้ใช้วิธี count() สำหรับรายการ สิ่งอันดับ ฯลฯ

หากค่าที่ไม่มีอยู่ในองค์ประกอบถูกส่งเป็นอาร์กิวเมนต์ ระบบจะส่งคืน 0

l = ['a', 'a', 'a', 'a', 'b', 'c', 'c']

print(l.count('a'))
# 4

print(l.count('b'))
# 1

print(l.count('c'))
# 2

print(l.count('d'))
# 0

หากคุณต้องการรับจำนวนครั้งของแต่ละองค์ประกอบในคราวเดียว คอลเล็กชันต่อไปนี้ ตัวนับมีประโยชน์

วิธีใช้ collections.Counter

คอลเล็กชันไลบรารีมาตรฐานของ Python มีคลาส Counter

Counter() เป็นคลาสย่อยของ dict ประเภทพจนานุกรม ซึ่งมีข้อมูลในรูปแบบขององค์ประกอบเป็นคีย์และเกิดขึ้นเป็นค่า

import collections

l = ['a', 'a', 'a', 'a', 'b', 'c', 'c']

c = collections.Counter(l)
print(c)
# Counter({'a': 4, 'c': 2, 'b': 1})

print(type(c))
# <class 'collections.Counter'>

print(issubclass(type(c), dict))
# True

หากระบุองค์ประกอบเป็นคีย์ สามารถรับจำนวนองค์ประกอบได้ หากมีการระบุค่าที่ไม่มีอยู่ในองค์ประกอบ ระบบจะส่งคืน 0

print(c['a'])
# 4

print(c['b'])
# 1

print(c['c'])
# 2

print(c['d'])
# 0

คุณยังสามารถใช้วิธีประเภทพจนานุกรม เช่น คีย์ (), ค่า (), รายการ () เป็นต้น

print(c.keys())
# dict_keys(['a', 'b', 'c'])

print(c.values())
# dict_values([4, 1, 2])

print(c.items())
# dict_items([('a', 4), ('b', 1), ('c', 2)])

เมธอดเหล่านี้ส่งคืนอ็อบเจ็กต์ประเภท dict_keys เป็นต้น ซึ่งสามารถใช้ได้เหมือนกับที่คุณต้องการเรียกใช้คำสั่ง for หากคุณต้องการแปลงเป็นรายการ ให้ใช้ list()

การรับองค์ประกอบตามลำดับความถี่ของลักษณะที่ปรากฏ: most_common() method

ตัวนับมีเมธอด most_common() ซึ่งส่งคืนรายการทูเพิลของแบบฟอร์ม (องค์ประกอบ จำนวนครั้ง) ที่จัดเรียงตามจำนวนครั้งที่เกิดขึ้น

print(c.most_common())
# [('a', 4), ('c', 2), ('b', 1)]

องค์ประกอบที่มีจำนวนครั้งสูงสุดสามารถรับได้โดยการระบุดัชนี เช่น [0] สำหรับจำนวนครั้งสูงสุดและ [-1] สำหรับจำนวนครั้งน้อยที่สุด หากคุณต้องการรับเฉพาะองค์ประกอบหรือจำนวนครั้งเท่านั้น คุณสามารถระบุดัชนีเพิ่มเติมได้

print(c.most_common()[0])
# ('a', 4)

print(c.most_common()[-1])
# ('b', 1)

print(c.most_common()[0][0])
# a

print(c.most_common()[0][1])
# 4

หากคุณต้องการเรียงลำดับตามจำนวนครั้งที่เกิดลดลง ให้ใช้สไลซ์โดยตั้งค่าส่วนเพิ่มเป็น -1

print(c.most_common()[::-1])
# [('b', 1), ('c', 2), ('a', 4)]

หากระบุอาร์กิวเมนต์ n สำหรับเมธอด most_common() จะส่งคืนเฉพาะองค์ประกอบ n รายการที่มีจำนวนครั้งสูงสุดเท่านั้น หากละเว้นองค์ประกอบทั้งหมด

print(c.most_common(2))
# [('a', 4), ('c', 2)]

หากคุณต้องการแยกรายการองค์ประกอบ/รายการโดยเรียงลำดับตามจำนวนการเกิดขึ้น แทนที่จะเป็นทูเพิล (องค์ประกอบ จำนวนรายการ) คุณสามารถแยกย่อยได้ดังนี้

values, counts = zip(*c.most_common())

print(values)
# ('a', 'c', 'b')

print(counts)
# (4, 2, 1)

ฟังก์ชันในตัว zip() ใช้เพื่อย้ายรายการสองมิติ (ในกรณีนี้คือรายการทูเพิล) จากนั้นแกะและแตกไฟล์

นับจำนวน (ประเภท) ขององค์ประกอบที่ไม่ทับซ้อนกัน (องค์ประกอบที่ไม่ซ้ำ)

ในการนับจำนวนองค์ประกอบที่ไม่ทับซ้อนกัน (องค์ประกอบที่ไม่ซ้ำ) ที่มีอยู่ในรายการหรือทูเพิล (มีกี่ประเภท) ให้ใช้ตัวนับหรือ set() ตามที่อธิบายไว้ข้างต้น

จำนวนองค์ประกอบในวัตถุ Counter เท่ากับจำนวนขององค์ประกอบที่ไม่ทับซ้อนกันในรายการดั้งเดิม ซึ่งสามารถรับได้ด้วย len()

l = ['a', 'a', 'a', 'a', 'b', 'c', 'c']
c = collections.Counter(l)

print(len(c))
# 3

คุณยังสามารถใช้ set() ตัวสร้างสำหรับชุดประเภทชุด ซึ่งจะง่ายกว่าถ้าคุณไม่ต้องการวัตถุตัวนับ

ประเภทชุดเป็นประเภทข้อมูลที่ไม่มีองค์ประกอบที่ซ้ำกัน การส่งรายการไปที่ set() จะละเว้นค่าที่ซ้ำกันและส่งคืนอ็อบเจ็กต์ประเภท set โดยมีค่าเฉพาะเป็นองค์ประกอบ จำนวนขององค์ประกอบประเภทนี้ได้มาจาก len()

print(set(l))
# {'a', 'c', 'b'}

print(len(set(l)))
# 3

นับจำนวนองค์ประกอบที่ตรงตามเงื่อนไข

ในการนับจำนวนองค์ประกอบในรายการหรือทูเพิลที่ตรงตามเงื่อนไขที่กำหนด ให้ใช้สัญลักษณ์ความเข้าใจรายการหรือนิพจน์ตัวสร้าง

ตัวอย่างเช่น นับจำนวนองค์ประกอบที่มีค่าลบสำหรับรายการตัวเลขต่อไปนี้

l = list(range(-5, 6))
print(l)
# [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]

การใช้นิพจน์เงื่อนไขกับแต่ละองค์ประกอบในสัญลักษณ์ความเข้าใจแบบรายการจะทำให้ได้รายการที่มีองค์ประกอบเป็นบูลีนบูล (จริง เท็จ) บูลประเภทบูลีนเป็นคลาสย่อยของ int ชนิดจำนวนเต็ม โดยที่ true ถือเป็น 1 และเท็จเป็น 0 ดังนั้น จำนวนค่าจริง (จำนวนองค์ประกอบที่ตรงตามเงื่อนไข) สามารถนับได้โดยการคำนวณผลรวมโดยใช้ผลรวม ().

print([i < 0 for i in l])
# [True, True, True, True, True, False, False, False, False, False, False]

print(sum([i < 0 for i in l]))
# 5

หากเราแทนที่ [] ในสัญกรณ์ความเข้าใจรายการด้วย () เราจะได้รับนิพจน์ตัวสร้าง สัญกรณ์ความเข้าใจรายการจะสร้างรายการขององค์ประกอบทั้งหมดที่ประมวลผล ในขณะที่นิพจน์ของตัวสร้างจะประมวลผลองค์ประกอบตามลำดับ ดังนั้นจึงมีประสิทธิภาพในหน่วยความจำมากกว่า

เมื่อนิพจน์ตัวสร้างเป็นอาร์กิวเมนต์เดียว () สามารถละเว้นได้ จึงสามารถเขียนได้ในกรณีหลัง

print(sum((i < 0 for i in l)))
# 5

print(sum(i < 0 for i in l))
# 5

หากคุณต้องการนับจำนวนค่าเท็จ (จำนวนองค์ประกอบที่ไม่เป็นไปตามเงื่อนไข) ให้ใช้อย่า โปรดทราบว่า > มีลำดับความสำคัญที่สูงกว่า (คำนวณก่อน) ดังนั้นวงเล็บ () ใน (i < 0) ในตัวอย่างต่อไปนี้จึงไม่จำเป็น

print([not (i < 0) for i in l])
# [False, False, False, False, False, True, True, True, True, True, True]

print(sum(not (i < 0) for i in l))
# 6

แน่นอนเงื่อนไขสามารถเปลี่ยนแปลงได้

print(sum(i >= 0 for i in l))
# 6

ตัวอย่างอื่น ๆ แสดงไว้ด้านล่าง

ตัวอย่างการรับจำนวนองค์ประกอบคี่สำหรับรายการตัวเลข

print([i % 2 == 1 for i in l])
# [True, False, True, False, True, False, True, False, True, False, True]

print(sum(i % 2 == 1 for i in l))
# 6

ตัวอย่างเงื่อนไขสำหรับรายการสตริง

l = ['apple', 'orange', 'banana']

print([s.endswith('e') for s in l])
# [True, True, False]

print(sum(s.endswith('e') for s in l))
# 2

ตัวนับใช้เพื่อนับตามจำนวนครั้งที่เกิดขึ้น items() ดึง tuple ของ (องค์ประกอบ, จำนวนครั้ง) และจำนวนครั้งที่เกิดขึ้นจะระบุเงื่อนไข

ต่อไปนี้คือตัวอย่างการแยกองค์ประกอบที่มีสองรายการขึ้นไปและนับจำนวนครั้งทั้งหมด ในตัวอย่างนี้ มีสี่ตัวและสอง c รวมเป็นหก

l = ['a', 'a', 'a', 'a', 'b', 'c', 'c']
c = collections.Counter(l)

print(c.items())
# dict_items([('a', 4), ('b', 1), ('c', 2)])

print([i for i in l if c[i] >= 2])
# ['a', 'a', 'a', 'a', 'c', 'c']

print([i[1] for i in c.items() if i[1] >= 2])
# [4, 2]

print(sum(i[1] for i in c.items() if i[1] >= 2))
# 6

ต่อไปนี้เป็นตัวอย่างการแยกประเภทขององค์ประกอบที่มีสองรายการขึ้นไปและนับจำนวนครั้งที่เกิดขึ้น ในตัวอย่างนี้ มีสองประเภทคือ a และ c

print([i[0] for i in c.items() if i[1] >= 2])
# ['a', 'c']

print([i[1] >= 2 for i in c.items()])
# [True, False, True]

print(sum(i[1] >= 2 for i in c.items()))
# 2

นับจำนวนครั้งของคำในสตริง

เป็นตัวอย่างที่ชัดเจน ลองนับจำนวนครั้งของคำในสตริง

ขั้นแรก แทนที่เครื่องหมายจุลภาคและมหัพภาคที่ไม่จำเป็นด้วยสตริงว่างโดยใช้เมธอด replace() แล้วลบทิ้ง จากนั้น ใช้เมธอด split() เพื่อสร้างรายการโดยคั่นด้วยช่องว่าง

s = 'government of the people, by the people, for the people.'

s_remove = s.replace(',', '').replace('.', '')

print(s_remove)
# government of the people by the people for the people

word_list = s_remove.split()

print(word_list)
# ['government', 'of', 'the', 'people', 'by', 'the', 'people', 'for', 'the', 'people']

หากคุณสร้างรายการได้ คุณจะได้รับจำนวนครั้งที่แต่ละคำปรากฏขึ้น ประเภทของคำที่ปรากฏ และ most_common() ของ collections.Counter เพื่อให้ได้คำที่ปรากฏบ่อยที่สุด

print(word_list.count('people'))
# 3

print(len(set(word_list)))
# 6

c = collections.Counter(word_list)

print(c)
# Counter({'the': 3, 'people': 3, 'government': 1, 'of': 1, 'by': 1, 'for': 1})

print(c.most_common()[0][0])
# the

ข้างต้นเป็นกระบวนการที่ง่ายมาก ดังนั้นควรใช้ไลบรารีเช่น NLTK สำหรับการประมวลผลภาษาธรรมชาติที่ซับซ้อนมากขึ้น

นอกจากนี้ ในกรณีของข้อความภาษาญี่ปุ่น ไม่สามารถใช้ split() เพื่อแยกข้อความได้เนื่องจากไม่มีการแยกคำที่ชัดเจน ตัวอย่างเช่น คุณสามารถใช้ไลบรารี Janome เพื่อทำสิ่งนี้ให้สำเร็จ

นับจำนวนการเกิดขึ้นของอักขระในสตริง

เนื่องจากสตริงเป็นประเภทลำดับด้วย จึงสามารถใช้กับเมธอด count() หรือส่งผ่านเป็นอาร์กิวเมนต์ไปยังตัวสร้างของ collections.Counter()

s = 'supercalifragilisticexpialidocious'

print(s.count('p'))
# 2

c = collections.Counter(s)

print(c)
# Counter({'i': 7, 's': 3, 'c': 3, 'a': 3, 'l': 3, 'u': 2, 'p': 2, 'e': 2, 'r': 2, 'o': 2, 'f': 1, 'g': 1, 't': 1, 'x': 1, 'd': 1})

ตัวอย่างการดึงอักขระ 5 อันดับแรกที่เกิดขึ้นบ่อยที่สุด

print(c.most_common(5))
# [('i', 7), ('s', 3), ('c', 3), ('a', 3), ('l', 3)]

values, counts = zip(*c.most_common(5))

print(values)
# ('i', 's', 'c', 'a', 'l')