在HDF5数据中查找唯一列

2024-04-28 05:58:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用HDF5来存储uint8s(400x1210000000)的非常大的数据集。列中存在大量冗余(97%的列不是唯一的)。我需要有效地合并重复的列。这意味着我需要删除重复的列,同时存储元数据以记住合并了哪些列。在

我目前使用Python和^ {CD3>},但是如果有人有一个高效的C++解决方案,我可以简单地使用^ }来实现它。在

我当前的解决方案是将数据集的块加载到NumPy数组中,并使用dictionary来存储唯一的列和元数据。在

注意:可以找到HashableNDArrayhere。我刚把它改名了。在

def find_column_redundancy(dataset):
    n_columns = dataset.shape[1]
    block_size = 500000
    n_blocks = int(ceil(float(n_columns) / float(block_size)))

    d = {}
    analysed_column_count = 0
    for block in xrange(n_blocks):
        block_offset = block*block_size
        block_data = dataset[:, block_offset : block_offset+block_size]
        for i in xrange(block_data.shape[1]):
            hashable_array = HashableNDArray(np.ascontiguousarray(block_data[:, i]))
            d[hashable_array] = np.append(d.get(hashable_array, np.array([], dtype=np.int32)), block_offset + i)
            analysed_column_count += 1

    return d

遍历所有列之后,我返回一个dictionary,我用它来编写一个新的HDF5数据集,去掉冗余。在

我需要帮助,这不可能是最好的!在

谢谢!在


Tags: columns数据datasizedictionarynpcolumn解决方案
1条回答
网友
1楼 · 发布于 2024-04-28 05:58:54

我用kernprof做了一些分析,并优化了我的代码。在

  • 最大的瓶颈是HashableNDArray对象的实例化。我发现,通过使numpy数组为只读,我可以散列它们的数据缓冲区,而不必使用包装器类。对于数据的提取,哈希处理的速度似乎要快得多。为了恢复列数据,我使用np.frombuffer(dict_key, dtype=np.uint8)

  • 我还通过将dictionary替换为defaultdict并消除try/except块,获得了一个小的加速。

  • 由于我的数据只包含二进制值,我发现在列上使用np.packbits可以在存储键时节省8倍的内存,并且仍然允许匹配相同的列。使用np.unpackbits时,唯一需要记住的是列的实际长度,因为numpy填充了不完整的字节,后面有0。

最后,我微调了块大小以使用最大可用内存量。这允许稍长的磁盘读取时间和更好的CPU使用率。在

这个函数以前在我的数据上运行大约18小时,现在只需要~0.5小时!在

def find_column_redundancy(dataset):
    n_columns = dataset.shape[1]
    block_size = 10000000
    n_blocks = int(ceil(float(n_columns) / float(block_size)))

    d = defaultdict(list)
    analysed_column_count = 0
    for block in xrange(n_blocks):
        block_offset = block*block_size
        block_data = dataset[:, block_offset : block_offset+block_size]
        block_data = np.asfortranarray(block_data)
        block_data = np.packbits(block_data, axis=0)
        block_data.flags.writeable = False
        for i in xrange(block_data.shape[1]):
            d[block_data[:, i].data[:]].append(block_offset + i)
            analysed_column_count += 1

        print float(analysed_column_count)/n_columns*100, "% completed. Dictionnary has", len(d), "items."

return d

相关问题 更多 >