Contare il numero di occorrenze di ogni elemento in una lista con Counter di Python

Attività commerciale

In Python, il numero di tutti gli elementi in una lista o tupla può essere ottenuto usando la funzione built-in len(), e il numero di ogni elemento (il numero di occorrenze di ogni elemento) può essere ottenuto usando il metodo count().

Inoltre, la classe Counter delle collezioni della libreria standard di Python può essere usata per ottenere gli elementi in ordine di numero di occorrenze.

In questa sezione, discuteremo quanto segue

  • Conta il numero totale di elementi:len()
  • Conta il numero di ogni elemento (il numero di occorrenze di ogni elemento):count()
  • Uso.collections.Counter
  • Gli elementi sono recuperati in ordine di frequenza di occorrenza:most_common()
  • Conta il numero (tipo) di elementi non sovrapposti (elementi unici).
  • Conta il numero di elementi che soddisfano la condizione.

Inoltre, come esempio concreto, viene spiegato quanto segue con codice di esempio.

  • Conta il numero di occorrenze di una parola in una stringa.
  • Conta il numero di occorrenze di un carattere in una stringa.

L'esempio è una lista, ma la stessa elaborazione può essere fatta con le tuple.

Conta il numero totale di elementi: len()

Per contare il numero totale di elementi in una lista o tupla, usate la funzione built-in len().

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

print(len(l))
# 7

Contare il numero di ogni elemento (il numero di occorrenze di ogni elemento): metodo count()

Per contare il numero di ogni elemento (il numero di occorrenze di ogni elemento), usate il metodo count() per liste, tuple, ecc.

Se un valore che non esiste come elemento viene passato come argomento, viene restituito 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

Se volete ottenere il numero di occorrenze di ogni elemento in una volta sola, il seguente collection.Counter è utile.

Come usare collections.Counter

Le collezioni della libreria standard di Python hanno una classe Counter.

Counter() è una sottoclasse del tipo dizionario dict, che ha dati sotto forma di elementi come chiavi e occorrenze come valori.

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

Se viene specificato un elemento come chiave, si può ottenere il numero di elementi. Se viene specificato un valore che non esiste come elemento, viene restituito 0.

print(c['a'])
# 4

print(c['b'])
# 1

print(c['c'])
# 2

print(c['d'])
# 0

Potete anche usare metodi di tipo dizionario come keys(), values(), items(), ecc.

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

Questi metodi restituiscono oggetti di tipo dict_keys, ecc. Possono essere usati così come sono se volete eseguire un'istruzione for. Se volete convertirli in una lista, usate list().

Ottenere elementi in ordine di frequenza di apparizione: metodo most_common()

Counter ha il metodo most_common(), che restituisce una lista di tuple della forma (elemento, numero di occorrenze) ordinate per numero di occorrenze.

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

L'elemento con il maggior numero di occorrenze può essere ottenuto specificando un indice, come [0] per il maggior numero di occorrenze e [-1] per il minor numero di occorrenze. Se volete ottenere solo gli elementi o solo il numero di occorrenze, potete specificare ulteriormente l'indice.

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

Se volete ordinarli in ordine di numero decrescente di occorrenze, usate la slice con l'incremento impostato a -1.

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

Se l'argomento n è specificato per il metodo most_common(), vengono restituiti solo gli n elementi con il maggior numero di occorrenze. Se viene omesso, tutti gli elementi.

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

Se volete una lista separata di elementi-occorrenze ordinata per numero di occorrenze, piuttosto che una tupla di (elemento, numero di occorrenze), potete decomporla come segue

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

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

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

La funzione built-in zip() è usata per trasporre una lista bidimensionale (in questo caso, una lista di tuple), e poi scompattarla ed estrarla.

Conta il numero (tipo) di elementi non sovrapposti (elementi unici).

Per contare quanti elementi non sovrapposti (elementi unici) ci sono in una lista o tupla (quanti tipi ci sono), usate Counter o set() come descritto sopra.

Il numero di elementi nell'oggetto Counter è uguale al numero di elementi non sovrapposti nella lista originale, che può essere ottenuto con len().

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

print(len(c))
# 3

Potete anche usare set(), il costruttore del tipo set, che è più facile se non avete bisogno di un oggetto Counter.

Il tipo set è un tipo di dati che non ha elementi duplicati. Passare una lista a set() ignora i valori duplicati e restituisce un oggetto di tipo set con solo valori unici come elementi. Il numero di elementi di questo tipo si ottiene con len().

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

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

Conta il numero di elementi che soddisfano la condizione.

Per contare il numero di elementi in una lista o tupla che soddisfano una certa condizione, usate la notazione di comprensione della lista o le espressioni generatrici.

Come esempio, contate il numero di elementi con valori negativi per la seguente lista di numeri

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

Applicando un'espressione condizionale ad ogni elemento nella notazione di comprensione della lista si ottiene una lista i cui elementi sono booleani (vero, falso). Il tipo booleano bool è una sottoclasse del tipo intero int, dove true è trattato come 1 e false come 0. Pertanto, il numero di valori veri (il numero di elementi che soddisfano la condizione) può essere contato calcolando la somma usando 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

Se sostituiamo [] nella notazione di comprensione della lista con (), otteniamo un'espressione generatrice. La notazione di comprensione della lista genera una lista di tutti gli elementi processati, mentre l'espressione generatrice processa gli elementi in modo sequenziale ed è quindi più efficiente in termini di memoria.

Quando l'espressione del generatore è l'unico argomento, () può essere omesso, quindi può essere scritto come nel secondo caso.

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

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

Se volete contare il numero di valori falsi (il numero di elementi che non soddisfano la condizione), usate not. Notate che > ha una precedenza maggiore di not (viene calcolato per primo), quindi le parentesi () in (i < 0) nell'esempio seguente non sono necessarie.

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

Naturalmente, le condizioni stesse possono essere cambiate.

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

Alcuni altri esempi sono mostrati qui sotto.

Esempio di come ottenere il numero di elementi dispari per una lista di numeri.

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

Esempio di condizione per una lista di stringhe.

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

Counter è usato per contare in base al numero di occorrenze. items() recupera una tupla di (elemento, numero di occorrenze), e il numero di occorrenze specifica la condizione.

Quello che segue è un esempio di estrazione di elementi con due o più occorrenze e conteggio del numero totale di occorrenze. In questo esempio, ci sono quattro a e due c, per un totale di sei.

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

Quello che segue è un esempio di estrazione dei tipi di elementi con due o più occorrenze e di conteggio del numero di occorrenze. In questo esempio, ci sono due tipi, a e 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

Conta il numero di occorrenze di una parola in una stringa.

Come esempio concreto, contiamo il numero di occorrenze di una parola in una stringa.

Per prima cosa, sostituite le virgole e i punti non necessari con una stringa vuota usando il metodo replace(), e poi cancellateli. Poi, usate il metodo split() per creare una lista separata da spazi.

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

Se potete fare una lista, potete ottenere il numero di volte che ogni parola appare, i tipi di parole che appaiono, e la most_common() di collections.Counter per ottenere la parola che appare più volte.

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

Questo è un processo molto semplice, quindi è meglio usare librerie come NLTK per l'elaborazione del linguaggio naturale più complesso.

Inoltre, nel caso del testo giapponese, split() non può essere usato per dividere il testo perché non c'è una chiara separazione delle parole. Per esempio, potete usare la libreria Janome per ottenere questo risultato.

Conta il numero di occorrenze di un carattere in una stringa.

Poiché anche le stringhe sono un tipo di sequenza, possono essere usate con il metodo count() o passate come argomento al costruttore di 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})

Esempio di recupero dei primi 5 caratteri più frequenti.

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