salvare - unire due liste python




Come contare le occorrenze di un elemento della lista? (15)

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à.

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


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

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

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

È 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}

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

Per contare il numero di diversi elementi che hanno un tipo comune:

li = ['A0','c5','A8','A2','A5','c2','A3','A9']

print sum(1 for el in li if el[0]=='A' and el[1] in '01234')

3 , non 6


Potrebbe non essere il più efficiente, richiede un pass extra per rimuovere i duplicati.

Implementazione funzionale:

arr = np.array(['a','a','b','b','b','c'])
print(set(map(lambda x  : (x , list(arr).count(x)) , arr)))

ritorna :

{('c', 1), ('b', 3), ('a', 2)}

o tornare come dict :

print(dict(map(lambda x  : (x , list(arr).count(x)) , arr)))

ritorna :

{'b': 3, 'c': 1, 'a': 2}

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

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

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

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


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]

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

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)

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

Ciò restituirà la quantità di occorrenze di your_value





count