2009-12-21 9 views

Respuesta

17

Si desea utilizar un juego de los elementos, aquí hay otra, probablemente más rápido w Ay:

y = set(x.flatten()) 

PD: después de realizar comparaciones entre x.flat, x.flatten() y x.ravel() en una matriz de 10x100, descubrí que todos ellos realizan aproximadamente a la misma velocidad. Para una matriz de 3x3, la versión más rápida es la versión iterador:

y = set(x.flat) 

que lo recomiendo porque es la versión costosa menos memoria (que se amplía hasta bien con el tamaño de la matriz).

PS: También hay una función NumPy que hace algo similar:

y = numpy.unique(x) 

Esto hace producir una matriz NumPy con el mismo elemento que set(x.flat), sino como una matriz NumPy. Esto es muy rápido (casi 10 veces más rápido), pero si necesita un set, entonces hacer set(numpy.unique(x)) es un poco más lento que los otros procedimientos (construir un conjunto viene con una gran sobrecarga).

+2

¡Buena sugerencia! También podría usar set (x.ravel()), que hace lo mismo pero crea una copia solo si es necesario. O mejor, use set (x.flat). x.flat es un iterador sobre los elementos de la matriz aplanada, pero no pierde tiempo al acoplar realmente la matriz – musicinmybrain

+0

@musicinmybrain: ¡muy buenos puntos! ¡Gracias! – EOL

+2

ADVERTENCIA: esta respuesta * no * le dará un conjunto de vectores, sino un conjunto de números. Si quiere un conjunto de vectores, entonces vea la respuesta de miku debajo de la cual convierte los vectores a tuplas – conradlee

9

La contraparte inmutable a un array es la tupla, por lo tanto, trata de convertir la matriz de matrices en un conjunto de tuplas:

>> from numpy import * 
>> x = array([[3,2,3],[4,4,4]]) 

>> x_hashable = map(tuple, x) 

>> y = set(x_hashable) 
set([(3, 2, 3), (4, 4, 4)]) 
+0

y cómo lo fácil/eficiente transformo de nuevo a una lista? – user989762

+0

'map (array, y)' – Manuel

3

Si desea utilizar un juego de los elementos:

>> y = set(e for r in x 
      for e in r) 
set([2, 3, 4]) 

Para un conjunto de las filas:

>> y = set(tuple(r) for r in x) 
set([(3, 2, 3), (4, 4, 4)]) 
6

Las respuestas anteriores funcionan si desea crear un conjunto de los elementos contenida en un ndarray, pero si desea crear un conjunto de ndarray objetos - o utilizar ndarray objetos como claves en un diccionario - entonces Tendrás que proporcionarles un envoltorio lavable. Ver el código de abajo para un ejemplo sencillo:

from hashlib import sha1 

from numpy import all, array, uint8 


class hashable(object): 
    r'''Hashable wrapper for ndarray objects. 

     Instances of ndarray are not hashable, meaning they cannot be added to 
     sets, nor used as keys in dictionaries. This is by design - ndarray 
     objects are mutable, and therefore cannot reliably implement the 
     __hash__() method. 

     The hashable class allows a way around this limitation. It implements 
     the required methods for hashable objects in terms of an encapsulated 
     ndarray object. This can be either a copied instance (which is safer) 
     or the original object (which requires the user to be careful enough 
     not to modify it). 
    ''' 
    def __init__(self, wrapped, tight=False): 
     r'''Creates a new hashable object encapsulating an ndarray. 

      wrapped 
       The wrapped ndarray. 

      tight 
       Optional. If True, a copy of the input ndaray is created. 
       Defaults to False. 
     ''' 
     self.__tight = tight 
     self.__wrapped = array(wrapped) if tight else wrapped 
     self.__hash = int(sha1(wrapped.view(uint8)).hexdigest(), 16) 

    def __eq__(self, other): 
     return all(self.__wrapped == other.__wrapped) 

    def __hash__(self): 
     return self.__hash 

    def unwrap(self): 
     r'''Returns the encapsulated ndarray. 

      If the wrapper is "tight", a copy of the encapsulated ndarray is 
      returned. Otherwise, the encapsulated ndarray itself is returned. 
     ''' 
     if self.__tight: 
      return array(self.__wrapped) 

     return self.__wrapped 

Uso de la clase contenedora es bastante simple:

>>> from numpy import arange 

>>> a = arange(0, 1024) 
>>> d = {} 
>>> d[a] = 'foo' 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
TypeError: unhashable type: 'numpy.ndarray' 
>>> b = hashable(a) 
>>> d[b] = 'bar' 
>>> d[b] 
'bar' 
Cuestiones relacionadas