【发布时间】:2019-08-27 23:20:31
【问题描述】:
将 numpy 对象保存到 parquet 的传统方法是使用 Pandas 作为中间体。但是,我正在处理大量数据,这些数据不适合 Pandas 而不会破坏我的环境,因为在 Pandas 中,数据占用了大量 RAM。
我需要保存到 Parquet,因为我正在使用 numpy 中的可变长度数组,因此对于该 parquet 实际上保存到比 .npy 或 .hdf5 更小的空间。
以下代码是一个最小的示例,它下载我的一小部分数据,并在 pandas 对象和 numpy 对象之间进行转换以测量它们消耗了多少 RAM,并保存到 npy 和 parquet 文件以查看它们占用了多少磁盘空间.
# Download sample file, about 10 mbs
from sys import getsizeof
import requests
import pickle
import numpy as np
import pandas as pd
import os
def download_file_from_google_drive(id, destination):
URL = "https://docs.google.com/uc?export=download"
session = requests.Session()
response = session.get(URL, params = { 'id' : id }, stream = True)
token = get_confirm_token(response)
if token:
params = { 'id' : id, 'confirm' : token }
response = session.get(URL, params = params, stream = True)
save_response_content(response, destination)
def get_confirm_token(response):
for key, value in response.cookies.items():
if key.startswith('download_warning'):
return value
return None
def save_response_content(response, destination):
CHUNK_SIZE = 32768
with open(destination, "wb") as f:
for chunk in response.iter_content(CHUNK_SIZE):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
download_file_from_google_drive('1-0R28Yhdrq2QWQ-4MXHIZUdZG2WZK2qR', 'sample.pkl')
sampleDF = pd.read_pickle('sample.pkl')
sampleDF.to_parquet( 'test1.pqt', compression = 'brotli', index = False )
# Parquet file takes up little space
os.path.getsize('test1.pqt')
6594712
getsizeof(sampleDF)
22827172
sampleDF['totalCites2'] = sampleDF['totalCites2'].apply(lambda x: np.array(x))
#RAM reduced if the variable length batches are in numpy
getsizeof(sampleDF)
22401764
#Much less RAM as a numpy object
sampleNumpy = sampleDF.values
getsizeof(sampleNumpy)
112
# Much more space in .npy form
np.save( 'test2.npy', sampleNumpy)
os.path.getsize('test2.npy')
20825382
# Numpy savez. Not as good as parquet
np.savez_compressed( 'test3.npy', sampleNumpy )
os.path.getsize('test3.npy.npz')
9873964
【问题讨论】:
-
112这个数字毫无意义。一般来说,
sys.getsizeof并不是衡量内存使用的好方法。 -
测量内存使用的更好方法是什么?
-
对于
ndarraynbytes。这只是元素数量乘以每个元素的大小(通常为 4-8 字节)。DataFrame可能将其数据存储在类似大小的数组中。但是,如果您有数组或列表的数组(对象 dtype),那么您必须考虑这些对象的大小。没有一个数字或尺度;您必须了解数据对象的结构。 -
如果列中有很多重复值,那么 pandas 稀疏数据结构可能会有所帮助 - 请参阅 pandas.pydata.org/pandas-docs/stable/user_guide/sparse.html 以获取
pandas.SparseArray和其他文件的文档 -
使用你的笔记本我
pickle.loadsample.pkl文件。结果是DataFrame。换句话说,给定来源,您无法绕过 pandas。那是第二列中带有列表的版本。您的apply命令将它们转换为数组,尽管长度为 5 到 100 似乎没有太大区别。这是一个对象 dtype 列。
标签: python pandas numpy parquet