【问题标题】:Convert large hdf5 dataset written via pandas/pytables to vaex将通过 pandas/pytables 编写的大型 hdf5 数据集转换为 vaex
【发布时间】:2020-04-03 11:10:10
【问题描述】:

我有一个非常大的数据集,我通过 append 分块写入 hdf5,如下所示:

with pd.HDFStore(self.train_store_path) as train_store:
    for filepath in tqdm(filepaths):
        with open(filepath, 'rb') as file:
            frame = pickle.load(file)

        if frame.empty:
            os.remove(filepath)
            continue

        try:
            train_store.append(
                key='dataset', value=frame,
                min_itemsize=itemsize_dict)
            os.remove(filepath)
        except KeyError as e:
            print(e)
        except ValueError as e:
            print(frame)
            print(e)
        except Exception as e:
            print(e) 

数据太大,无法加载到一个 DataFrame 中,所以我想尝试 vaex 进行进一步处理。不过有几件事我不太明白。

由于 vaex 在 hdf5 中使用的表示形式与 pandas/pytables (VOTable) 不同,我想知道如何在这两种格式之间进行转换。我尝试将数据分块加载到 pandas 中,将其转换为 vaex DataFrame 然后存储它,但似乎无法将数据附加到现有的 vaex hdf5 文件中,至少我找不到。

真的没有办法从 vaex 中创建大型 hdf5 数据集吗?是将现有数据集转换为 vaex 表示的唯一选择(通过 python 脚本或 TOPCAT 构建文件)?

与我之前的问题有关,如果我在核心外使用 vaex 中的大型数据集,是否可以将我在 vaex 中应用的任何转换的结果保存到 hdf5 文件中?

【问题讨论】:

    标签: python pandas hdf5 pytables vaex


    【解决方案1】:

    这种存储格式的问题在于它不是基于列的,它不能很好地处理具有大量行的数据集,因为例如,如果您只使用 1 列,操作系统可能也会读取大量数据其他列的一部分以及 CPU 缓存被它污染。最好将它们存储为基于列的格式,例如 vaex 的 hdf5 格式或箭头。

    可以使用以下方法转换为 vaex 数据帧:

    import vaex
    vaex_df = vaex.from_pandas(pandas_df, copy_index=False)
    

    您可以对每个数据帧执行此操作,并将它们作为 hdf5 或箭头存储在磁盘上:

    vaex_df.export('batch_1.hdf5')  # or 'batch_1.arrow'
    

    如果您对许多文件执行此操作,您可以延迟(即不会制作内存副本)将它们连接起来,或使用 vaex.open 函数:

    df1 = vaex.open('batch_1.hdf5')
    df2 = vaex.open('batch_2.hdf5')
    df = vaex.concat([df1, df2]) # will be seen as 1 dataframe without mem copy
    df_altnerative = vaex.open('batch*.hdf5')  # same effect, but only needs 1 line
    

    关于你关于转换的问题:

    如果您对数据框进行转换,您可以写出计算值,或获取包含转换的“状态”:

    import vaex
    df = vaex.example()
    df['difference'] = df.x - df.y
    # df.export('materialized.hdf5', column_names=['difference'])  # do this if IO is fast, and memory abundant
    # state = df.state_get()  # get state in memory
    df.state_write('mystate.json') # or write as json
    
    
    import vaex
    df = vaex.example()
    # df.join(vaex.open('materialized.hdf5'))  # join on rows number (super fast, 0 memory use!)
    # df.state_set(state)  # or apply the state from memory
    df.state_load('mystate.json')  # or from disk
    df
    

    【讨论】:

    • 谢谢,这很有帮助。不过,我仍然不能完全确定我理解 state 的事情。如果您使用 hdf5 并且希望将结果保存到磁盘(不仅仅是管道,而是实际结果),您只能一次写入 hdf5,所以您必须将其全部放入 RAM?状态是您对数据执行的操作的管道,对吗?由于我想创建一个对 ML 数据进行预处理的管道,并且在某些时候我想再次将转换后的数据保存在磁盘上,我开始认为 vaex 可能不是这个确切应用程序的正确工具。跨度>
    • 它不必放入 RAM,它将以“块”的形式导出,尽管磁盘上的最终结果是一个连续的数组。我认为你想要的可以用 vaex 完成,但这太短了,无法回答,也许会打开一个新问题?
    • 谢谢,我想我误读了关于内存丰富的评论。一旦遇到具体障碍,我会尝试一些东西并提出问题。
    • 熊猫数据框必须适合 RAM。此外,我的 vaex_df.export('batch_1.hdf5') 永远不会在 jupyterlab 中完成(即使在小文件上也是如此),并且写出的位是无法使用的。也无法读取 pandas 编写的 hdf5。是否没有为 vaex 逐行添加数据帧以便我可以循环遍历 JSON?
    最近更新 更多