我試圖執行設置一個python以下構建從numpy的矩陣
>> from numpy import *
>> x = array([[3,2,3],[4,4,4]])
>> y = set(x)
TypeError: unhashable type: 'numpy.ndarray'
我怎樣才能輕鬆而高效地創建一個從numpy的陣列一組?
我試圖執行設置一個python以下構建從numpy的矩陣
>> from numpy import *
>> x = array([[3,2,3],[4,4,4]])
>> y = set(x)
TypeError: unhashable type: 'numpy.ndarray'
我怎樣才能輕鬆而高效地創建一個從numpy的陣列一組?
如果你想一組的元素,這裏是另一個,可能更快,w^AY:
y = set(x.flatten())
PS:一個10x100陣列上x.flat
,x.flatten()
,和x.ravel()
之間執行比較後,我發現,它們都在大約相同的速度來執行。對於一個3x3的陣列,最快的版本是迭代版本:
y = set(x.flat)
,我會建議,因爲它是較少的內存便宜的版本(它擴展了很好地與數組的大小)。
PS:還有一個NumPy的函數,它類似的東西:
y = numpy.unique(x)
這確實產生NumPy的陣列作爲set(x.flat)
相同的元素,但作爲一個NumPy的陣列。這個速度非常快(幾乎快10倍),但是如果你需要set
,那麼做set(numpy.unique(x))
比其他程序慢一點(構建一個集會帶來很大的開銷)。
不可改變對應到一個數組元組,因此,儘量數組的數組轉換成元組的數組:
>> 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)])
以及如何我很容易/高效地把回單嗎? – user989762 2014-02-18 05:57:04
'map(array,y)' – Manuel 2014-03-26 12:07:59
如果你想一組的元素:
>> y = set(e for r in x
for e in r)
set([2, 3, 4])
對於集中行:
>> y = set(tuple(r) for r in x)
set([(3, 2, 3), (4, 4, 4)])
上述答案的工作,如果你想創建一組出元素包含在ndarray
,但如果你想創建一套ndarray
對象 - 或在字典中使用ndarray
對象作爲鍵 - 那麼你必須爲他們提供一個可以打包的包裝。請參見下面的代碼,一個簡單的例子:
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
使用包裝類是很簡單的:
>>> 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'
好建議!你也可以使用set(x.ravel()),它可以做同樣的事情,但只有在需要時才創建一個副本。或者,更好的是,使用set(x.flat)。 x.flat是迭代器,用於展平數組的元素,但不會浪費時間實際上展平數組 – musicinmybrain 2009-12-21 12:11:59
@musicinmybrain:非常好的一點!謝謝! – EOL 2009-12-21 14:23:10
警告:這個答案*不會給你一組向量,而是一組數字。如果你想要一組矢量然後看下面的miku的答案,將矢量轉換成元組 – conradlee 2011-08-02 11:30:13