2010-10-27 16 views
16

Tengo una matriz scipy, p.Manera eficiente de contar elementos únicos en la matriz en numpy/scipy en Python

a = array([[0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 0, 1]]) 

Quiero contar el número de ocurrencias de cada elemento único en la matriz. Por ejemplo, para la matriz anterior a, deseo ver que hay 1 aparición de [0, 0, 1], 2 apariciones de [1, 1, 1] y 1 aparición de [1, 0, 1].

Una manera pensé en hacerlo es:

from collections import defaultdict 
d = defaultdict(int) 

for elt in a: 
    d[elt] += 1 

es que hay una manera mejor/más eficiente?

gracias.

+0

¿Dónde está el uso de Numpy/Scipy en su código de ejemplo? ¿O se supone que esto solo atraviesa la idea, queriendo tener una función Numpy/Scipy para resolver esto? – Zelphir

Respuesta

8

Si se pegue con Python 2.7 (o 3.1) no es un problema y cualquiera de estas dos versiones de Python está disponible para usted, tal vez el nuevo collections.Counter podría haber algo para usted si usted se pega a hashable elementos como tuplas:

>>> from collections import Counter 
>>> c = Counter([(0,0,1), (1,1,1), (1,1,1), (1,0,1)]) 
>>> c 
Counter({(1, 1, 1): 2, (0, 0, 1): 1, (1, 0, 1): 1})

No he hecho ninguna prueba de rendimiento en estos dos enfoques, sin embargo.

+5

defaultdict será más rápido. John Machin mostró esto con los tiempos en una respuesta el día de hoy (http://stackoverflow.com/questions/4036474/add-new-keys-to-a-dictionary-while-incrementing-existing-values). –

+0

Es bueno saberlo :-) Gracias :-) –

+1

No usa Numpy/Scipy, como lo solicita el título del OP. También aboga por el uso de versiones desactualizadas de Python. No estoy seguro de que esta sea una buena respuesta. – Zelphir

1

para el pitón 2,6 <

import itertools 

data_array = [[0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 0, 1]] 

dict_ = {} 

for list_, count in itertools.groupby(data_array): 
    dict_.update({tuple(list_), len(list(count))}) 
4

Puede ordenar la matriz lexicográfico por filas y el aspecto de los puntos donde las filas cambian:

In [1]: a = array([[0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 0, 1]]) 

In [2]: b = a[lexsort(a.T)] 

In [3]: b 
Out[3]: 
array([[0, 0, 1], 
     [1, 0, 1], 
     [1, 1, 1], 
     [1, 1, 1]]) 

... 


In [5]: (b[1:] - b[:-1]).any(-1) 
Out[5]: array([ True, True, False], dtype=bool) 

La última serie dice que las tres primeras filas difieren y la tercera fila se repite dos veces.

Para las matrices de unos y ceros se puede codificar los valores:

In [6]: bincount(dot(a, array([4,2,1]))) 
Out[6]: array([0, 1, 0, 0, 0, 1, 0, 2]) 

Diccionarios también se pueden utilizar. Cuál de los varios métodos será el más rápido dependerá del tipo de matrices con las que realmente está trabajando.

0

El paquete numpy_indexed (descargo de responsabilidad: soy su autor) proporciona una solución similar a la publicada por chuck; que está muy bien vectorizado. Pero con las pruebas, una interfaz agradable y muchas más funciones útiles relacionadas:

import numpy_indexed as npi 
npi.count(a) 
Cuestiones relacionadas