Pyarrow table 内存与原始 csv 大小相比

Pyarrow table memory compared to raw csv size

我有一个 2GB 的 CSV 文件,我将其读入 pyarrow table,其中包含以下内容:

from pyarrow import csv

tbl = csv.read_csv(path)

当我调用 tbl.nbytes 时,我得到了 3.4GB。我很惊讶箭头内存中的 csv 比 csv 大得多。也许我对 pyarrow 在幕后所做的事情有一个根本性的误解,但我认为如果有的话,由于它的柱状性质,它会更小(我也可能使用 ConvertOptions 挤出更多收益,但我想要一个基线)。我绝对没想到会增加近 75%。此外,当我将它从箭头 table 转换为 pandas df 时,df 占用的内存量与 csv 大致相同——这是预期的。

任何人都可以帮助解释箭头 tables 与 csv / pandas df.

的内存差异

谢谢。

更新

完整代码和输出如下。

In [2]: csv.read_csv(r"C:\Users\matth\OneDrive\Data\Kaggle\sf-bay-area-bike-shar
   ...: e\status.csv")
Out[2]:
pyarrow.Table
station_id: int64
bikes_available: int64
docks_available: int64
time: string

In [3]: tbl = csv.read_csv(r"C:\Users\generic\OneDrive\Data\Kaggle\sf-bay-area-bik
   ...: e-share\status.csv")

In [4]: tbl.schema
Out[4]:
station_id: int64
bikes_available: int64
docks_available: int64
time: string

In [5]: tbl.nbytes
Out[5]: 3419272022

In [6]: tbl.to_pandas().info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 71984434 entries, 0 to 71984433
Data columns (total 4 columns):
 #   Column           Dtype
---  ------           -----
 0   station_id       int64
 1   bikes_available  int64
 2   docks_available  int64
 3   time             object
dtypes: int64(3), object(1)
memory usage: 2.1+ GB

有两个问题:

  1. 整数列使用 int64,但 int32 更合适(除非值很大)
  2. 时间列被解释为字符串。输入格式不遵循任何标准也无济于事 (%Y/%m/%d %H:%M:%S)

第一个问题很容易解决,使用ConvertionOptions:

tbl = csv.read_csv(
    <path>,
    convert_options=csv.ConvertOptions(
        column_types={
            'station_id': pa.int32(),
            'bikes_available': pa.int32(),
            'docks_available': pa.int32(),
            'time': pa.string()
        }))

第二个有点复杂,因为据我所知 read_csv API 不允许您提供时间列的格式,而且没有简单的方法在 pyarrow 中将字符串列转换为日期时间。所以你必须使用 pandas 代替:

series = tbl.column('time').to_pandas()
series_as_datetime = pd.to_datetime(series, format='%Y/%m/%d %H:%M:%S')
tbl2 = pa.table(
    {
        'station_id':tbl.column('station_id'),
        'bikes_available':tbl.column('bikes_available'),
        'docks_available':tbl.column('docks_available'),
        'time': pa.chunked_array([series_as_datetime])
    })
tbl2.nbytes
>>> 1475683759

1475683759 是您期望的数字,再好不过了。每行是 20 个字节 (4 + 4 + 4 + 8)。