h5py docs中,我看到可以使用数据集的astype方法将HDF数据集转换为另一种类型。这将返回一个contextmanager,该contextmanager动态执行转换。
但是,我想读入存储为uint16的数据集,然后将其转换为float32类型。此后,我想在另一个函数中从这个数据集中提取不同的片段作为cast类型float32。文档解释了

with dataset.astype('float32'):
   castdata = dataset[:]

这将导致整个数据集被读入并转换为float32,这不是我想要的。我想要一个对数据集的引用,但将其转换为float32等价于numpy.astype。如何创建对.astype('float32')对象的引用,以便将其传递给另一个函数使用?
例如:
import h5py as HDF
import numpy as np
intdata = (100*np.random.random(10)).astype('uint16')

# create the HDF dataset
def get_dataset_as_float():
    hf = HDF.File('data.h5', 'w')
    d = hf.create_dataset('data', data=intdata)
    print(d.dtype)
    # uint16

    with d.astype('float32'):
    # This won't work since the context expires. Returns a uint16 dataset reference
       return d

    # this works but causes the entire dataset to be read & converted
    # with d.astype('float32'):
    #   return d[:]

此外,astype上下文似乎只在访问数据元素时才适用。这意味着
def use_data():
   d = get_data_as_float()
   # this is a uint16 dataset

   # try to use it as a float32
   with d.astype('float32'):
       print(np.max(d))   # --> output is uint16
       print(np.max(d[:]))   # --> output is float32, but entire data is loaded

所以没有一种新的方式来使用astype吗?

最佳答案

d.astype()返回一个AstypeContext对象。如果您查看AstypeContext的源代码,您将更好地了解发生了什么:

class AstypeContext(object):

    def __init__(self, dset, dtype):
        self._dset = dset
        self._dtype = numpy.dtype(dtype)

    def __enter__(self):
        self._dset._local.astype = self._dtype

    def __exit__(self, *args):
        self._dset._local.astype = None

当你进入AstypeContext时,你的数据集的._local.astype属性会被更新到新的期望类型,当你退出上下文时,它会变回原来的值。
因此,你可以或多或少地得到你想要的行为:
def get_dataset_as_type(d, dtype='float32'):

    # creates a new Dataset instance that points to the same HDF5 identifier
    d_new = HDF.Dataset(d.id)

    # set the ._local.astype attribute to the desired output type
    d_new._local.astype = np.dtype(dtype)

    return d_new

当您现在从d_new读取时,您将得到float32numpy数组,而不是uint16
d = hf.create_dataset('data', data=intdata)
d_new = get_dataset_as_type(d, dtype='float32')

print(d[:])
# array([81, 65, 33, 22, 67, 57, 94, 63, 89, 68], dtype=uint16)
print(d_new[:])
# array([ 81.,  65.,  33.,  22.,  67.,  57.,  94.,  63.,  89.,  68.], dtype=float32)

print(d.dtype, d_new.dtype)
# uint16, uint16

注意,这不会更新.dtyped_new属性(它似乎是不可变的)。如果您还想更改dtype属性,那么您可能需要对h5py.Dataset进行子类化。

关于python - 使用Astype在H5py中创建对HDF数据集的引用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25241096/

10-11 07:32