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
有两个问题:
- 整数列使用 int64,但 int32 更合适(除非值很大)
- 时间列被解释为字符串。输入格式不遵循任何标准也无济于事 (
%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)。
我有一个 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
有两个问题:
- 整数列使用 int64,但 int32 更合适(除非值很大)
- 时间列被解释为字符串。输入格式不遵循任何标准也无济于事 (
%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)。