Počítání počtu výskytů jednotlivých prvků v seznamu pomocí funkce Counter v jazyce Python

Podnikání

V jazyce Python lze počet všech prvků seznamu nebo trojice získat pomocí vestavěné funkce len() a počet jednotlivých prvků (počet výskytů každého prvku) lze získat pomocí metody count().

Kromě toho lze k získání prvků v pořadí podle počtu výskytů použít třídu Counter ze standardní knihovny Python collections.

V této části se budeme zabývat následujícími otázkami

  • Spočítejte celkový počet prvků:len()
  • Spočítejte počet jednotlivých prvků (počet výskytů každého prvku):count()
  • Použití.collections.Counter
  • Prvky jsou vyhledávány v pořadí podle četnosti výskytu:most_common()
  • Spočítejte počet (typ) nepřekrývajících se prvků (jedinečných prvků).
  • Spočítá počet prvků, které splňují podmínku.

Kromě toho je jako konkrétní příklad vysvětlen následující postup s ukázkovým kódem.

  • Spočítá počet výskytů slova v řetězci.
  • Spočítá počet výskytů znaku v řetězci.

Ukázka je seznam, ale stejné zpracování lze provést i s tuply.

Spočítá celkový počet prvků: len()

Chcete-li spočítat celkový počet prvků v seznamu nebo trojici, použijte vestavěnou funkci len().

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

print(len(l))
# 7

Počítání počtu jednotlivých prvků (počet výskytů jednotlivých prvků): metoda count()

Chcete-li spočítat počet jednotlivých prvků (počet výskytů každého prvku), použijte metodu count() pro seznamy, tuply atd.

Pokud je jako argument předána hodnota, která jako prvek neexistuje, je vrácena hodnota 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

Pokud chcete zjistit počet výskytů každého prvku najednou, je užitečný následující příkaz collection.Counter.

Jak používat collections.Counter

Kolekce standardní knihovny Pythonu obsahují třídu Counter.

Čítač() je podtřída slovníkového typu dict, který má data ve formě prvků jako klíčů a výskytů jako hodnot.

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

Pokud je jako klíč zadán prvek, lze získat počet prvků. Pokud je jako prvek zadána hodnota, která neexistuje, je vrácena 0.

print(c['a'])
# 4

print(c['b'])
# 1

print(c['c'])
# 2

print(c['d'])
# 0

Můžete také použít metody typu slovník, jako jsou keys(), values(), items() atd.

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)])

Tyto metody vracejí objekty typu dict_keys atd. Pokud chcete spustit příkaz for, můžete je použít tak, jak jsou. Pokud je chcete převést na seznam, použijte funkci list().

Získání prvků podle četnosti výskytu: metoda most_common()

Čítač má metodu most_common(), která vrací seznam tuplů tvaru (prvek, počet výskytů) seřazených podle počtu výskytů.

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

Prvek s nejvyšším počtem výskytů lze získat zadáním indexu, například [0] pro nejvyšší počet výskytů a [-1] pro nejnižší počet výskytů. Pokud chcete získat pouze prvky nebo pouze počet výskytů, můžete index zadat dále.

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

Pokud je chcete seřadit podle klesajícího počtu výskytů, použijte řez s přírůstkem nastaveným na -1.

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

Pokud je u metody most_common() zadán argument n, je vráceno pouze n prvků s nejvyšším počtem výskytů. Pokud je vynechán, budou vráceny všechny prvky.

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

Chcete-li získat samostatný seznam prvků\výskytů seřazený podle počtu výskytů, nikoli tuple (prvek, počet výskytů), můžete jej rozložit takto

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

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

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

Vestavěná funkce zip() slouží k transpozici dvourozměrného seznamu (v tomto případě seznamu tuplů) a jeho následnému rozbalení a extrakci.

Spočítejte počet (typ) nepřekrývajících se prvků (jedinečných prvků).

Chcete-li spočítat, kolik nepřekrývajících se prvků (unikátních prvků) je v seznamu nebo tuplu (kolik typů existuje), použijte výše popsané funkce Counter nebo set().

Počet prvků v objektu Čítač je roven počtu nepřekrývajících se prvků v původním seznamu, který lze zjistit pomocí funkce len().

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

print(len(c))
# 3

Můžete také použít set(), konstruktor pro typ set, což je jednodušší, pokud nepotřebujete objekt Counter.

Typ množiny je datový typ, který nemá duplicitní prvky. Předání seznamu funkci set() ignoruje duplicitní hodnoty a vrací objekt typu set, jehož prvky jsou pouze jedinečné hodnoty. Počet prvků tohoto typu se zjistí pomocí funkce len().

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

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

Spočítá počet prvků, které splňují podmínku.

Chcete-li spočítat počet prvků seznamu nebo tuple, které splňují určitou podmínku, použijte notaci pro porozumění seznamu nebo generátorové výrazy.

Jako příklad spočítejte počet prvků se zápornými hodnotami pro následující seznam čísel

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

Použitím podmíněného výrazu na každý prvek v notaci pro porozumění seznamu získáme seznam, jehož prvky jsou logické booly (true, false). Booleovský typ bool je podtřídou celočíselného typu int, kde true je považováno za 1 a false za 0. Proto lze počet pravdivých hodnot (počet prvků, které splňují podmínku) spočítat výpočtem součtu pomocí funkce sum().

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

Nahradíme-li [] v zápisu pro porozumění seznamu za (), získáme generátorový výraz. Zápis pro porozumění seznamu generuje seznam všech zpracovávaných prvků, zatímco generátorový výraz zpracovává prvky postupně, a je proto paměťově úspornější.

Pokud je výraz generátoru jediným argumentem, lze () vynechat, takže jej lze zapsat jako v druhém případě.

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

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

Pokud chcete spočítat počet nepravdivých hodnot (počet prvků, které nesplňují podmínku), použijte not. Všimněte si, že > má vyšší prioritu než not (počítá se jako první), takže závorky () v (i < 0) v následujícím příkladu nejsou nutné.

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

Samotné podmínky lze samozřejmě změnit.

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

Některé další příklady jsou uvedeny níže.

Příklad získání počtu lichých prvků pro seznam čísel.

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

Příklad podmínky pro seznam řetězců.

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

Čítač slouží k počítání na základě počtu výskytů. items() načte tuple (prvek, počet výskytů) a počet výskytů určuje podmínku.

Následuje příklad extrakce prvků se dvěma nebo více výskyty a spočítání celkového počtu výskytů. V tomto příkladu se vyskytují čtyři a a dvě c, celkem tedy šest.

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

Následuje příklad extrakce typů prvků se dvěma a více výskyty a počítání počtu výskytů. V tomto příkladu se vyskytují dva typy, a 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

Spočítá počet výskytů slova v řetězci.

Jako konkrétní příklad uveďme počet výskytů slova v řetězci.

Nejprve nahraďte nepotřebné čárky a tečky prázdným řetězcem pomocí metody replace() a poté je odstraňte. Poté pomocí metody split() vytvořte seznam oddělený mezerami.

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']

Pokud dokážete vytvořit seznam, můžete získat počet výskytů jednotlivých slov, typy slov, které se v něm objevují, a pomocí funkce most_common() funkce collections.Counter získat slovo, které se v něm objevuje nejčastěji.

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

Výše uvedený postup je velmi jednoduchý, takže pro složitější zpracování přirozeného jazyka je lepší použít knihovny, jako je NLTK.

V případě japonského textu také nelze použít funkci split() k rozdělení textu, protože v něm nejsou jasně oddělena slova. K tomu můžete použít například knihovnu Janome.

Spočítá počet výskytů znaku v řetězci.

Protože řetězce jsou také sekvenčním typem, lze je použít pomocí metody count() nebo je předat jako argument konstruktoru metody 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})

Příklad načtení 5 nejčastěji se vyskytujících znaků.

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')