python concatenare - Come contare le occorrenze di un elemento della lista?




liste unire (19)

Ho confrontato tutte le soluzioni suggerite (e alcune nuove) con perfplot (un mio piccolo progetto).

Conteggio di un oggetto

Per array abbastanza grandi, si scopre che

numpy.sum(numpy.array(a) == 1) 

è leggermente più veloce rispetto alle altre soluzioni.

Conteggio di tutti gli oggetti

Come stabilito in precedenza ,

numpy.bincount(a)

è quello che vuoi

Codice per riprodurre i grafici:

from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot


def counter(a):
    return Counter(a)


def count(a):
    return dict((i, a.count(i)) for i in set(a))


def bincount(a):
    return numpy.bincount(a)


def pandas_value_counts(a):
    return pandas.Series(a).value_counts()


def occur_dict(a):
    d = {}
    for i in a:
        if i in d:
            d[i] = d[i]+1
        else:
            d[i] = 1
    return d


def count_unsorted_list_items(items):
    counts = defaultdict(int)
    for item in items:
        counts[item] += 1
    return dict(counts)


def operator_countof(a):
    return dict((i, operator.countOf(a, i)) for i in set(a))


perfplot.show(
    setup=lambda n: list(numpy.random.randint(0, 100, n)),
    n_range=[2**k for k in range(20)],
    kernels=[
        counter, count, bincount, pandas_value_counts, occur_dict,
        count_unsorted_list_items, operator_countof
        ],
    equality_check=None,
    logx=True,
    logy=True,
    )

2.

from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot


def counter(a):
    return Counter(a)


def count(a):
    return dict((i, a.count(i)) for i in set(a))


def bincount(a):
    return numpy.bincount(a)


def pandas_value_counts(a):
    return pandas.Series(a).value_counts()


def occur_dict(a):
    d = {}
    for i in a:
        if i in d:
            d[i] = d[i]+1
        else:
            d[i] = 1
    return d


def count_unsorted_list_items(items):
    counts = defaultdict(int)
    for item in items:
        counts[item] += 1
    return dict(counts)


def operator_countof(a):
    return dict((i, operator.countOf(a, i)) for i in set(a))


perfplot.show(
    setup=lambda n: list(numpy.random.randint(0, 100, n)),
    n_range=[2**k for k in range(20)],
    kernels=[
        counter, count, bincount, pandas_value_counts, occur_dict,
        count_unsorted_list_items, operator_countof
        ],
    equality_check=None,
    logx=True,
    logy=True,
    )

Dato un oggetto, come posso contare le sue occorrenze in una lista in Python?


se vuoi un numero di occorrenze per l'elemento in particolare:

>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> single_occurrences = Counter(z)
>>> print(single_occurrences.get("blue"))
3
>>> print(single_occurrences.values())
dict_values([3, 2, 1])

È stato suggerito di utilizzare il bincount di bincount , tuttavia funziona solo per gli array 1d con numeri interi non negativi . Inoltre, l'array risultante potrebbe confondere (contiene le occorrenze dei numeri interi da min a max dell'elenco originale e imposta a 0 gli interi mancanti).

Un modo migliore per farlo con numpy è utilizzare la funzione unique con l'attributo return_counts impostato su True. Restituisce una tupla con una matrice di valori univoci e una matrice di occorrenze di ciascun valore univoco.

# a = [1, 1, 0, 2, 1, 0, 3, 3]
a_uniq, counts = np.unique(a, return_counts=True)  # array([0, 1, 2, 3]), array([2, 3, 1, 2]

e quindi possiamo accoppiarli come

dict(zip(a_uniq, counts))  # {0: 2, 1: 3, 2: 1, 3: 2}

Funziona anche con altri tipi di dati e "liste 2d", ad es

>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']]
>>> dict(zip(*np.unique(a, return_counts=True)))
{'a': 3, 'b': 3, 'c': 2}


Perché non usare Panda?

import pandas as pd

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

# converting the list to a Series and counting the values
my_count = pd.Series(l).value_counts()
my_count

Produzione:

a    3
d    2
b    1
c    1
dtype: int64

Se stai cercando un conteggio di un particolare elemento, ad esempio a , prova:

my_count['a']

Produzione:

3

Un altro modo per ottenere il numero di occorrenze di ciascun elemento, in un dizionario:

dict((i, a.count(i)) for i in a)

def countfrequncyinarray(arr1):
    r=len(arr1)
    return {i:arr1.count(i) for i in range(1,r+1)}
arr1=[4,4,4,4]
a=countfrequncyinarray(arr1)
print(a)

Se stai usando Python 2.7 o 3 e vuoi il numero di occorrenze per ogni elemento:

>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> Counter(z)
Counter({'blue': 3, 'red': 2, 'yellow': 1})

Se puoi usare i pandas , allora value_counts è lì per il salvataggio.

>>> import pandas as pd
>>> a = [1, 2, 3, 4, 1, 4, 1]
>>> pd.Series(a).value_counts()
1    3
4    2
3    1
2    1
dtype: int64

Ordina automaticamente il risultato in base alla frequenza.

Se vuoi che il risultato sia in una lista di liste, fai come sotto

>>> pd.Series(a).value_counts().reset_index().values.tolist()
[[1, 3], [4, 2], [3, 1], [2, 1]]

sum([1 for elem in <yourlist> if elem==<your_value>])

Ciò restituirà la quantità di occorrenze di your_value


from collections import Counter
country=['Uruguay', 'Mexico', 'Uruguay', 'France', 'Mexico']
count_country = Counter(country)
output_list= [] 

for i in count_country:
    output_list.append([i,count_country[i]])
print output_list

Lista di uscita:

[['Mexico', 2], ['France', 1], ['Uruguay', 2]]

Dato un oggetto, come posso contare le sue occorrenze in una lista in Python?

Ecco un elenco di esempio:

>>> l = list('aaaaabbbbcccdde')
>>> l
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']

list.count

C'è il metodo list.count

>>> l.count('b')
4

Questo funziona bene per qualsiasi lista. Anche le tuple hanno questo metodo:

>>> t = tuple('aabbbffffff')
>>> t
('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')
>>> t.count('f')
6

collections.Counter

E poi ci sono collezioni.Counter. È possibile scaricare qualsiasi iterabile in un contatore, non solo in un elenco, e il contatore manterrà una struttura di dati dei conteggi degli elementi.

Uso:

>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4

I contatori sono basati su dizionari Python, le loro chiavi sono gli elementi, quindi le chiavi devono essere lavabili. Sono fondamentalmente come insiemi che consentono di inserire elementi ridondanti.

Ulteriore utilizzo di collections.Counter

Puoi aggiungere o sottrarre con iterables dal tuo contatore:

>>> c.update(list('bbb'))
>>> c['b']
7
>>> c.subtract(list('bbb'))
>>> c['b']
4

E puoi anche fare operazioni multi-set con il contatore:

>>> c2 = Counter(list('aabbxyz'))
>>> c - c2                   # set difference
Counter({'a': 3, 'c': 3, 'b': 2, 'd': 2, 'e': 1})
>>> c + c2                   # addition of all elements
Counter({'a': 7, 'b': 6, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c | c2                   # set union
Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c & c2                   # set intersection
Counter({'a': 2, 'b': 2})

Perché non i panda?

Un'altra risposta suggerisce:

Perché non usare i panda?

Pandas è una libreria comune, ma non è nella libreria standard. Aggiungerlo come requisito non è banale.

Esistono soluzioni integrate per questo caso d'uso nell'oggetto list stesso e nella libreria standard.

Se il tuo progetto non richiede già dei panda, sarebbe sciocco renderlo un requisito solo per questa funzionalità.


Di seguito sono le tre soluzioni:

Il più veloce utilizza un ciclo for e lo memorizza in un Dict.

import time
from collections import Counter


def countElement(a):
    g = {}
    for i in a:
        if i in g: 
            g[i] +=1
        else: 
            g[i] =1
    return g


z = [1,1,1,1,2,2,2,2,3,3,4,5,5,234,23,3,12,3,123,12,31,23,13,2,4,23,42,42,34,234,23,42,34,23,423,42,34,23,423,4,234,23,42,34,23,4,23,423,4,23,4]


#Solution 1 - Faster
st = time.monotonic()
for i in range(1000000):
    b = countElement(z)
et = time.monotonic()
print(b)
print('Simple for loop and storing it in dict - Duration: {}'.format(et - st))

#Solution 2 - Fast
st = time.monotonic()
for i in range(1000000):
    a = Counter(z)
et = time.monotonic()
print (a)
print('Using collections.Counter - Duration: {}'.format(et - st))

#Solution 3 - Slow
st = time.monotonic()
for i in range(1000000):
    g = dict([(i, z.count(i)) for i in set(z)])
et = time.monotonic()
print(g)
print('Using list comprehension - Duration: {}'.format(et - st))

Risultato

#Solution 1 - Faster
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 234: 3, 23: 10, 12: 2, 123: 1, 31: 1, 13: 1, 42: 5, 34: 4, 423: 3}
Simple for loop and storing it in dict - Duration: 12.032000000000153
#Solution 2 - Fast
Counter({23: 10, 4: 6, 2: 5, 42: 5, 1: 4, 3: 4, 34: 4, 234: 3, 423: 3, 5: 2, 12: 2, 123: 1, 31: 1, 13: 1})
Using collections.Counter - Duration: 15.889999999999418
#Solution 3 - Slow
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 34: 4, 423: 3, 234: 3, 42: 5, 12: 2, 13: 1, 23: 10, 123: 1, 31: 1}
Using list comprehension - Duration: 33.0

# Python >= 2.6 (defaultdict) && < 2.7 (Counter, OrderedDict)
from collections import defaultdict
def count_unsorted_list_items(items):
    """
    :param items: iterable of hashable items to count
    :type items: iterable

    :returns: dict of counts like Py2.7 Counter
    :rtype: dict
    """
    counts = defaultdict(int)
    for item in items:
        counts[item] += 1
    return dict(counts)


# Python >= 2.2 (generators)
def count_sorted_list_items(items):
    """
    :param items: sorted iterable of items to count
    :type items: sorted iterable

    :returns: generator of (item, count) tuples
    :rtype: generator
    """
    if not items:
        return
    elif len(items) == 1:
        yield (items[0], 1)
        return
    prev_item = items[0]
    count = 1
    for item in items[1:]:
        if prev_item == item:
            count += 1
        else:
            yield (prev_item, count)
            count = 1
            prev_item = item
    yield (item, count)
    return


import unittest
class TestListCounters(unittest.TestCase):
    def test_count_unsorted_list_items(self):
        D = (
            ([], []),
            ([2], [(2,1)]),
            ([2,2], [(2,2)]),
            ([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
            )
        for inp, exp_outp in D:
            counts = count_unsorted_list_items(inp) 
            print inp, exp_outp, counts
            self.assertEqual(counts, dict( exp_outp ))

        inp, exp_outp = UNSORTED_WIN = ([2,2,4,2], [(2,3), (4,1)])
        self.assertEqual(dict( exp_outp ), count_unsorted_list_items(inp) )


    def test_count_sorted_list_items(self):
        D = (
            ([], []),
            ([2], [(2,1)]),
            ([2,2], [(2,2)]),
            ([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
            )
        for inp, exp_outp in D:
            counts = list( count_sorted_list_items(inp) )
            print inp, exp_outp, counts
            self.assertEqual(counts, exp_outp)

        inp, exp_outp = UNSORTED_FAIL = ([2,2,4,2], [(2,3), (4,1)])
        self.assertEqual(exp_outp, list( count_sorted_list_items(inp) ))
        # ... [(2,2), (4,1), (2,1)]

Conta di tutti gli elementi con itertools.groupby()

La possibilità di Antoher per ottenere il conteggio di tutti gli elementi nell'elenco potrebbe essere tramite itertools.groupby() .

Conteggi "duplicati"

from itertools import groupby

L = ['a', 'a', 'a', 't', 'q', 'a', 'd', 'a', 'd', 'c']  # Input list

counts = [(i, len(list(c))) for i,c in groupby(L)]      # Create value-count pairs as list of tuples 
print(counts)

ritorna

[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]

Notate come ha combinato i primi tre a come primo gruppo, mentre altri gruppi di a sono presenti più in basso nell'elenco. Ciò accade perché l'elenco di input L non è stato ordinato. Questo può essere un vantaggio a volte se i gruppi dovessero essere separati.

Conteggi unici

Se sono desiderati conteggi di gruppo univoci, basta ordinare l'elenco di input:

counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)

ritorna

[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]

Conteggio delle occorrenze di un elemento in un elenco

Per contare le occorrenze di un solo elemento della lista puoi usare count()

>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2

Il conteggio delle occorrenze di tutti gli elementi in una lista è anche noto come "conteggio" di un elenco o creazione di un contatore di conteggi.

Conteggio di tutti gli articoli con conteggio ()

Per contare le occorrenze di elementi in l si può semplicemente usare una comprensione di lista e il metodo count()

[[x,l.count(x)] for x in set(l)]

(o similmente con un dizionario dict((x,l.count(x)) for x in set(l)) )

Esempio:

>>> l = ["a","b","b"]
>>> [[x,l.count(x)] for x in set(l)]
[['a', 1], ['b', 2]]
>>> dict((x,l.count(x)) for x in set(l))
{'a': 1, 'b': 2}

Conteggio di tutti gli elementi con Contatore ()

In alternativa, c'è la classe Counter più veloce dalla libreria delle collections

Counter(l)

Esempio:

>>> l = ["a","b","b"]
>>> from collections import Counter
>>> Counter(l)
Counter({'b': 2, 'a': 1})

Quanto è più veloce Counter?

Ho controllato quanto più veloce è il Counter per le liste di controllo. Ho provato entrambi i metodi con alcuni valori di n e sembra che Counter sia più veloce di un fattore costante di circa 2.

Ecco lo script che ho usato:

from __future__ import print_function
import timeit

t1=timeit.Timer('Counter(l)', \
                'import random;import string;from collections import Counter;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
                )

t2=timeit.Timer('[[x,l.count(x)] for x in set(l)]',
                'import random;import string;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
                )

print("Counter(): ", t1.repeat(repeat=3,number=10000))
print("count():   ", t2.repeat(repeat=3,number=10000)

E l'output:

Counter():  [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]
count():    [7.779430688009597, 7.962715800967999, 8.420845870045014]

Se si desidera contare tutti i valori contemporaneamente, è possibile farlo molto velocemente utilizzando gli array e il bincount come segue

import numpy as np
a = np.array([1, 2, 3, 4, 1, 4, 1])
np.bincount(a)

che dà

>>> array([0, 3, 1, 1, 2])

È inoltre possibile utilizzare il metodo countOf di un operator modulo incorporato.

>>> import operator
>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)
3

Se si desidera una nuova lista mantenendo le due vecchie liste:

def concatenate_list(listOne, listTwo):
    joinedList = []
    for i in listOne:
        joinedList.append(i)
    for j in listTwo:
        joinedList.append(j)

    sorted(joinedList)

    return joinedList




python list count