有没有更快的方法来使用pandas连接巨大的数据帧(40GB)

Is there a faster way to concat huge data frames (40GB) using pandas

我有 3 个 40 GB 大小的巨大数据框,我使用块打开它们。然后,我想将它们连接在一起。这是我尝试过的:

    path = 'path/to/myfiles'
    files = [os.path.join(path,i) for i in os.listdir(path) if i.endswith('tsv')]
    for file in files:
        cols = ['col1','col2','col3']
        chunks = pd.read_table(file, sep='\t', names=cols, chunksize=10000000)

但是,当我尝试连接所有文件时,它会花费很长时间。 我想提出一些建议来连接所有数据帧 quicker/faster.

.tsv.csv 相对于 read/write 来说是相当慢的格式。我发现镶木地板最适合我最终做的大部分事情。它的读写速度非常快,还允许您轻松地将文件的分块文件夹作为单个 table 读回。它确实需要字符串列名,但是:

In [102]: df = pd.DataFrame(np.random.random((100000, 100)), columns=[str(i) for i in range(100)])

In [103]: %time df.to_parquet("out.parquet")
Wall time: 980 ms

In [104]: %time df.to_csv("out.csv")
Wall time: 14 s

In [105]: %time df = pd.read_parquet("out.parquet")
Wall time: 195 ms

In [106]: %time df = pd.read_csv("out.csv")
Wall time: 1.53 s

如果您无法控制这些分块文件的格式,您显然需要至少支付一次读取它们的费用,但从长远来看,转换它们仍然可以为您节省一些时间 运行 如果你做了很多其他 read/writes.

  1. CSV/TSV 是一种非常慢的文件格式,未优化。
  2. 您可能不需要将整个数据集保存在内存中。您的用例可能不需要对整个组合 (120GB) 数据集进行完全随机的列和行访问 .
  • (你能连续处理每个 row/chunk/group(例如邮政编码、user_id 等)吗?例如计算聚合、汇总统计、特征?或者你是否需要能够应用任意跨列(哪些列)或行(哪些列)进行过滤?例如 “获取过去 N 天内使用服务 X 的所有用户 ID”。您可以选择更高性能的文件格式根据您的用例。还有其他文件格式(HDFS、PARQUET 等)。有些针对列访问或行访问进行了优化,有些针对顺序或随机访问进行了优化。还有 PySpark。
  • 您不一定需要将数据集组合成一个巨大的 120GB 文件。
  1. 你说运行时很慢,但很可能你正在耗尽内存(在这种情况下运行时会耗尽 window),所以你首先要检查你的内存使用情况。
  • 您的代码试图读入并存储每个文件的所有块,而不是在三个文件中逐块处理它们for file in files: ... chunks = pd.read_table(file, ... chunksize=10000000)。参见 Iterating through files chunk by chunk, in pandas
  • 修复后,chunksize=1e7参数不是内存块的大小;它只是块中的行数。这个值大得离谱。如果组合数据帧的一行要占用 10Kb,那么一大块 1e7 这样的行将占用 100Gb(!),这不适合大多数机器。
  1. 如果您必须坚持使用 CSV,对三个文件中的每一个文件处理一个块,然后将其输出写入文件,不要让所有块都在内存中徘徊。 同时减少你的块大小(尝试例如 1e5 或更少,并测量内存和运行时的改进)。也不要对其进行硬编码,找出每台机器的合理值,and/or 使其成为命令行参数。监控您的内存使用情况。