[英]suppress numpy array creation protocol for numpy arrays of objects
我正在嘗試建立一個庫來讀取python中的復雜HDF5數據文件。
我遇到一個問題,其中HDF5 Dataset
以某種方式實現了默認的數組協議(有時),從而當從中創建一個numpy數組時,它會轉換為特定的數組類型。
In [8]: ds
Out[8]: <HDF5 dataset "two_by_zero_empty_matrix": shape (2,), type "<u8">
In [9]: ds.value
Out[9]: array([2, 0], dtype=uint64)
此Dataset
對象實現numpy數組協議,並且當數據集由數字組成時,它將提供默認的數組類型。
In [10]: np.array(ds)
Out[10]: array([2, 0], dtype=uint64)
但是,如果數據集不是數字,而是其他一些對象(如您所料),它僅使用np.object
類型的numpy數組:
In [43]: ds2
Out[43]: <HDF5 dataset "somecells": shape (2, 3), type "|O8">
In [44]: np.array(ds2)
Out[44]:
array([[<HDF5 object reference>, <HDF5 object reference>,
<HDF5 object reference>],
[<HDF5 object reference>, <HDF5 object reference>,
<HDF5 object reference>]], dtype=object)
這種行為似乎很方便,但是在我看來,這實際上很不方便,因為它會干擾我對數據文件的遞歸遍歷。 事實證明,解決它確實很困難,因為有很多可能的數據類型必須根據其是對象的孩子還是數字的數組加以特殊的處理。
我的問題是:有沒有一種方法可以抑制默認的數組創建協議,以便可以從要轉換為其自然鴨子類型的數據集對象中創建對象數組?
也就是說,我想要類似np.array(ds, dtype=object)
,它將產生[<Dataset object of type int>, dtype=object]
而不是[3 4 5, dtype=int]
的數組。
但是np.array(ds, dtype=np.object)
拋出IOError: Can't read data (No appropriate function for conversion path)
我認真地嘗試了一些有關numpy數組協議的文檔,並發現了很多東西,但是在我看來,似乎沒有人考慮過有人想要這種行為。
我可以了解Out[44]
的來源。 它是一個包含對象指針的數組,在這種情況下, h5py
引用了文件上的對象(我認為)。
您是否嘗試使用np.array(ds, dtype=object)
而不是np.array(ds)
獲得的“普通”數組? array([2, 0], dtype=uint64)
。
但是什么是並行數組? 帶有ds
?指針的單個元素數組? 還是一個2元素數組,在文件中某處指向2
和0
指針? 如果不是<HDF5 object reference>
怎么辦?
在numpy
,沒有任何h5py
東西,我可以從值列表創建對象數組:
In [104]: np.array([2,0], dtype=object)
Out[104]: array([2, 0], dtype=object)
或者我可以從一個空數組開始(用None
填充)並賦值:
In [105]: x=np.empty((2,), dtype=object)
In [106]: x[0]=2
In [107]: x[1]=0
In [108]: x
Out[108]: array([2, 0], dtype=object)
我想您可以嘗試:
x[0] = ds[0]
or
x[:] = ds[:]
或制作單個元素對象數組
x = np.empty((), dtype=object)
x[()] = ds
我沒有在Ipython會話上打開h5py
測試文件來對此進行測試。 但是我可以做一些奇怪的事情,例如創建包含自身的對象數組。 我可以使用,但是沒有遞歸錯誤就無法顯示它。
In [118]: x=np.empty((),dtype=object)
In [119]: x[()]=x
In [120]: x1=x[()]
In [121]: x1==x
Out[121]: True
我在另一個終端上打開了一個小的h5py
文件:
In [315]: list(f.keys())
Out[315]: ['d', 'x', 'y']
In [317]: f['d'] # the group
Out[317]: <HDF5 group "/d" (2 members)>
x
是一個字符串:
In [318]: f['x'] # a single element (a string)
Out[318]: <HDF5 dataset "x": shape (), type "|O4">
In [330]: f['x'].value
Out[330]: 'astring'
In [331]: np.array(f['x'])
Out[331]: array('astring', dtype=object)
y
是一個數組:
In [320]: f['y'][:]
Out[320]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [321]: f['y'].value
Out[321]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [322]: np.array(f['y'])
Out[322]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [323]: timeit np.array(f['y'])
1000 loops, best of 3: 364 µs per loop
In [324]: timeit f['y'].value
1000 loops, best of 3: 380 µs per loop
因此,使用value
和array
訪問是等效的。
作為object
數組訪問會產生與您同樣的錯誤。
In [325]: np.array(f['y'],dtype=object)
...
OSError: can't read data (Dataset: Read failed)
轉換為浮點數效果很好:
In [326]: np.array(f['y'],dtype=float)
Out[326]: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
分配給預定義對象數組的工作原理是:
In [327]: x=np.empty((),dtype=object)
In [328]: x[()]=f['y']
In [329]: x
Out[329]: array(<HDF5 dataset "y": shape (10,), type "<i4">, dtype=object)
嘗試創建一個10個元素的數組,取y
:
In [332]: y1=np.empty((10,),dtype=object)
In [333]: y1[:]=f['y']
...
OSError: can't read data (Dataset: Read failed)
In [334]: y1[:]=f['y'].value
In [335]: y1
Out[335]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=object)
y1[:]=f['y'][:]
也可以
我無法將數據集分配給y1
(與嘗試np.array(f['y'],dtype=object)
時發生的錯誤相同。但是我可以分配其值。甚至可以將數據集分配給y1
一個元素
In [338]: y1[-1]=f['y']
In [339]: y1
Out[339]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8,
<HDF5 dataset "y": shape (10,), type "<i4">], dtype=object)
我繼續回到基本概念,即對象數組只是指針的集合,本質上是數組包裝器中的列表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.