【问题标题】:Parquet file larger than memory consumption of pandas DataFrameParquet文件大于pandas DataFrame的内存消耗
【发布时间】:2021-06-13 13:07:13
【问题描述】:

我将两个不同的 pandas DataFrames 存储为 parquet 文件(通过 kedro)。

在写入磁盘之前,两个 DataFrame 具有相同的尺寸和 dtypes (float32)。此外,它们在 RAM 中的内存消耗是相同的:

distances_1.memory_usage(deep=True).sum()/1e9
# 3.730033604
distances_2.memory_usage(deep=True).sum()/1e9
# 3.730033604

当保存为.parquet 文件时,第一个 df 生成一个 ~0.89GB 的文件,第二个文件生成一个 ~4.5GB 的文件。

distances_1 的冗余值比distances_2 多得多,因此压缩可能更有效。

将 parquet 文件从磁盘加载到 DataFrames 会产生与原始 DataFrames 相同的有效数据。

  • 如何解释文件之间的巨大差异?
  • 出于什么原因,第二个文件会比内存中的数据结构大?

【问题讨论】:

  • 将 RAM 转换为常用单位会不会更容易混淆?
  • 提供的代码以GB为单位返回数据帧的总内存消耗,对吧?我认为这样可以很容易地将其与文件大小进行比较。
  • 我明白了,只是有时(例如在 Windows 资源管理器中)单位 1GB 表示 2^30 Bytes
  • 这个“更多的冗余值”是否可以通过某种方式测量?
  • 当然你对 GB 的看法是对的,除以 1e9 只是一个近似值,但我认为这对这个问题并不重要,不是吗?

标签: python pandas parquet kedro


【解决方案1】:

正如您所说,唯一值的数量对镶木地板的大小起着非常重要的作用。

从 pandas 翻译过来,另外两个可能对 parquet 文件大小产生惊人影响的因素是:

  1. pandas 索引,即使只是自动分配,也会默认保存;
  2. 数据的排序,这可能会对有时使用的游程编码 parquet 产生很大的影响。

随机、自动分配的索引可能会占用大量空间。如果您不关心磁盘上数据的排序顺序,那么担心这一点可能会产生重大影响。

考虑一个 pandas 框架的四种情况,其中一列在所有情况下都包含相同的数据:前 2**16 个整数的圆角平方。以排序形式存储没有索引需要 2.9K;在没有自动分配索引的情况下洗牌需要 66K;自动分配索引然后改组需要 475K。

import pandas as pd
import numpy as np
!mkdir -p /tmp/parquet
d = pd.DataFrame({"A": np.floor(np.sqrt(np.arange(2**16)))})

d.to_parquet("/tmp/parquet/straight.parquet")
d.to_parquet("/tmp/parquet/straight_no_index.parquet", index = False)
d.sample(frac = 1).to_parquet("/tmp/parquet/shuf.parquet")
d.sample(frac = 1).to_parquet("/tmp/parquet/shuf_no_index.parquet", index = False)
ls -lSh /tmp/parquet
-rw-r--r--  1 user  wheel   475K Mar 18 13:39 shuf.parquet
-rw-r--r--  1 user  wheel    66K Mar 18 13:39 shuf_no_index.parquet
-rw-r--r--  1 user  wheel   3.3K Mar 18 13:39 straight.parquet
-rw-r--r--  1 user  wheel   2.9K Mar 18 13:39 straight_no_index.parquet

【讨论】:

  • 很好的信息,谢谢。在我的情况下,没有索引的写入会产生微小的差异(远小于 1 promille),但根本不能解释观察到的文件大小的巨大差异。我还需要保留行的顺序(尤其是在删除索引时)。
  • 你知道为什么它在磁盘上比在内存中大吗?
  • 在不知道数据的形状和引擎的情况下很难想到任何东西 正如 Wolf 所说,这可能是 Python 在内部进行哈希处理的东西。其他几种可能性:
  • (继续...)也许 parquet 可以存储的一些额外数据超出了 pandas 的内部结构(例如,每页索引提示)已经不正常了。也许不知何故,编码实际上正在失去空间,这可能会发生;或者您有 df.memory_usage(deep=True) 没有测量的表级信息。 (例如,如果您的列名每个都有一百万个字符长,它们会增加很多文件大小,但不会增加 df.memory_usage(),它不考虑它们)。
【解决方案2】:

从 Kedro 的角度来看,这只是调用 PyArrow 库 write_table 函数文档 here。这些参数中的任何一个都可以通过目录定义中的 save_args 参数获得,并且可能值得一试?

【讨论】:

    猜你喜欢
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 2016-01-29
    • 2018-03-01
    • 2014-07-31
    • 2015-04-04
    • 1970-01-01
    相关资源
    最近更新 更多