常见问题#

我有一个巨大的CSV文件,无法一次性全部加载到内存中。如何将其转换为HDF5?#

4.14 中的新功能:

由Apache Arrow支持,Vaex支持通过以下方式简单地懒加载CSV文件:

df = vaex.open('./my_data/my_big_file.csv')

通过这种方式,您可以处理任意大的CSV文件,使用相同的API,就像处理HDF5、Apache Arrow或Apache Parquet文件一样。

出于性能考虑,我们确实建议将大型CSV文件转换为HDF5或Apache Arrow格式。这可以通过以下方式简单完成:

df = vaex.open('./my_data/my_big_file.csv', convert='./my_data/my_big_file.hdf5')

也可以选择将大型CSV文件转换为Apache Parquet,以同样的方式节省磁盘空间。

4.14之前:

df = vaex.from_csv('./my_data/my_big_file.csv', convert=True, chunk_size=5_000_000)

当上述行被执行时,Vaex 将分块读取 CSV,并将每个块转换为磁盘上的临时 HDF5 文件。所有临时文件随后将被连接成一个单一的 HDF5 文件,并删除临时文件。可以通过 chunk_size 参数指定要读取的单个块的大小。

注意:在Vaex的较新版本中仍然可以这样做,但这不是最有效的方法。

有关使用Vaex导入和导出数据的更多信息,请参考I/O示例

为什么我无法打开从pandas DataFrame使用.to_hdf导出的HDF5文件?#

当使用pandas.to_hdf方法时,输出的HDF5文件是基于行的格式。而Vaex则期望基于列的HDF5文件。这使得数据列的读取更加高效,这在数据科学应用中更为常见。

可以轻松地将pandas DataFrame导出为vaex友好的HDF5文件:

vaex_df = vaex.from_pandas(pandas_df, copy_index=False)
vaex_df.export_hdf5('my_data.hdf5')

使用vaex的最佳文件格式是什么?#

“最优”可能取决于一个人试图实现的目标。一个简短的总结将是:

vaex 在数据以内存映射文件格式(即 HDF5、Apache Arrow 或 FITS)存储时表现出色。我们说一个文件可以内存映射,如果它在内存中的结构与在磁盘上的结构相同。尽管任何文件都可以内存映射,但如果需要反序列化,内存映射就没有优势。

原则上,HDF5和Arrow应该提供相同的性能。对于适合内存的文件,两者之间的性能是相同的。对于大于可用RAM的单个文件,我们的测试显示HDF5提供更快的性能。“更快”的含义可能取决于您的系统、数据的数量和类型。这种性能差异可能是由于将位掩码转换为字节掩码,或者由于展平分块的Arrow数组。我们预计这种性能差异将在未来消失。

如果你的数据分布在多个文件中,并且这些文件是动态连接的,那么HDF5和Arrow之间的性能预计是相同的。我们的测试显示,当所有数据都包含在一个文件中时,与多个文件相比,性能更好。

Arrow文件格式允许与其他生态系统无缝互操作。如果您的用例需要与其他生态系统(例如Java)共享数据,那么Arrow文件格式是您的最佳选择。

vaex 也支持 Parquet。Parquet 是压缩的,因此内存映射没有优势。使用 Parquet 时总是会有性能损失,因为数据在使用前需要解压缩。然而,Parquet 允许延迟读取数据,可以在需要时解压缩。因此,vaex 可以轻松处理大于 RAM 的 Parquet 文件。我们建议在希望节省磁盘空间时使用 Parquet。在从慢速 I/O 源(如旋转硬盘或云存储)读取时,它也可能很方便。请注意,通过使用 df.materialize,可以以内存或磁盘空间为代价获得与 HDF5 或 Arrow 文件相同的性能。

从技术上讲,vaex 可以使用来自 CSV 和 JSON 源的数据,但这样数据会被放入内存中,使用效果并不理想。我们强烈建议根据您的使用场景或偏好,将这些数据源以及其他任何数据源转换为 HDF5、Arrow 或 Parquet 文件格式。

为什么在过滤vaex DataFrame后无法添加新列?#

与其他库不同,vaex 不会复制或修改数据。例如,在过滤操作之后:

df2 = df[df.x > 5]

df2 仍然包含 df 中的所有数据。不同的是,df2 的列是惰性索引的,只有满足过滤条件的行才会显示或使用。这意味着原则上可以根据需要打开或关闭过滤器。

为了能够手动向过滤后的df2 DataFrame添加新列,首先需要使用df2.extract()方法。这将删除惰性索引,使df2的长度等于其过滤后的长度。

这是一个简短的示例:

[1]:
import vaex
import numpy as np

df = vaex.from_dict({'id': np.array([1, 2, 3, 4]),
                     'name': np.array(['Sally', 'Tom', 'Maria', 'John'])
                    })

df2 = df[df.id > 2]
df2 = df2.extract()

df2['age'] = np.array([27, 29])
df2
[1]:
# id姓名 年龄
0 3玛丽亚 27
1 4John 29