2013-06-04 2 views
5

Quindi, ho elenchi di parole e ho bisogno di sapere ogni quanto ogni parola appare su ogni lista. L'uso di ".count (word)" funziona, ma è troppo lento (ogni elenco ha migliaia di parole e ho migliaia di elenchi).Posso ingannare numpy.histogram in comportamenti come numpy.bincount?

Ho cercato di velocizzare le cose con Numpy. Ho generato un codice numerico univoco per ogni parola, quindi potrei usare numpy.bincount (dato che funziona solo con numeri interi, non con stringhe). Ma ottengo "ValueError: array è troppo grande".

Così ora sto cercando di modificare l'argomento "bin" della funzione numpy.histogram per fare in modo che restituisca i conteggi di frequenza di cui ho bisogno (in qualche modo numpy.histogram sembra non avere problemi con i big array). Ma finora non va bene. Qualcuno là fuori succede di averlo fatto prima? È possibile? C'è una soluzione più semplice che non riesco a vedere?

+0

Quanto è grande il tuo array !? Ho appena usato bincount con un array di lunghezza di 10000000 e ha funzionato bene. Ho esaurito la memoria prima di ottenere l'errore che fai. –

+1

Penso che il problema riguardi il tuo sistema di codice numerico univoco, non la dimensione degli array iniziali. np.bincount creerà una matrice di lunghezza pari a 1 + il numero intero più grande dell'array, il che, se stai usando una sorta di codifica con numeri ridicolmente grandi, potrebbe causare un problema. Tuttavia, non ho avuto problemi con np.bincount ([1000000000]). Qual è il tuo schema di codifica numerica? – cge

+1

Ah sembra che l'errore si verifica quando sei interi che stai cercando di bin sono enormi. Puoi emularlo con 'foo = numpy.random.randint (2 ** 62, size = 1000); numpy.bincount (foo) '. Immagino che stia cercando di creare un enorme array non indicizzabile per memorizzare tutti i bin e numpy sta dicendo no (quell'errore è in 'multiarray/ctors.c'). Quante parole hai? –

risposta

5

Non usare numpy per questo. Utilizzare invece collections.Counter. È progettato per questo caso d'uso.

+0

Questo è chiaramente il modo giusto per farlo se il problema è come descritto! –

+0

Fantastico! Pulito e superveloce. – Parzival

4

Perché non ridurre i numeri interi per l'insieme minimo utilizzando numpy.unique:

original_keys, lookup_vals = numpy.unique(big_int_string_array, return_inverse=True) 

È possibile poi basta usare numpy.bincount su lookup_vals, e se avete bisogno di tornare il numero intero unica stringa originale, si può semplicemente utilizzare il i valori di lookup_vals come indici a original_keys.

Quindi, qualcosa di simile:

import binascii 
import numpy 

string_list = ['a', 'b', 'c', 'a', 'b', 'd', 'c'] 
int_list = [binascii.crc32(string)**2 for string in string_list] 

original_keys, lookup_vals = numpy.unique(int_list, return_inverse=True) 

bins = bincount(lookup_vals) 

Inoltre, si evita la necessità di far quadrare i vostri numeri interi.

1

Thiago, Puoi anche provarlo direttamente dalle variabili categoriali con il metodo itemfreq di scipy. Ecco un esempio:

>>> import scipy as sp 
>>> import scipy.stats 
>>> rv = ['do', 're', 'do', 're', 'do', 'mi'] 
>>> note_frequency = sp.stats.itemfreq(rv) 
>>> note_frequency 
array([['do', '3'], 
     ['mi', '1'], 
     ['re', '2']], 
     dtype='|S2')