hea*_*n00 6 python memory csv pandas
所以我一直在尝试使用 pandasread_csv函数读取内存中的 3.2GB 文件,但我不断遇到某种内存泄漏,我的内存使用量会激增90%+。
所以还有替代方案
我尝试定义dtype以避免将数据作为字符串保留在内存中,但看到了类似的行为。
尝试了 numpy read csv,认为我会得到一些不同的结果,但这绝对是错误的。
尝试逐行阅读遇到了同样的问题,但速度非常慢。
我最近转向 python 3,所以认为那里可能存在一些错误,但在 python2 + pandas 上看到了类似的结果。
有问题的文件是来自 Kaggle 竞赛的 train.csv 文件组 bimbo的 train.csv 文件
系统信息:
RAM: 16GB, Processor: i7 8cores
如果您还想了解其他信息,请告诉我。
谢谢 :)
编辑1:它是一个内存峰值!不是泄漏(对不起,我的错。)
编辑 2:csv 文件示例
Semana,Agencia_ID,Canal_ID,Ruta_SAK,Cliente_ID,Producto_ID,Venta_uni_hoy,Venta_hoy,Dev_uni_proxima,Dev_proxima,Demanda_uni_equil
3,1110,7,3301,15766,1212,3,25.14,0,0.0,3
3,1110,7,3301,15766,1216,4,33.52,0,0.0,4
3,1110,7,3301,15766,1238,4,39.32,0,0.0,4
3,1110,7,3301,15766,1240,4,33.52,0,0.0,4
3,1110,7,3301,15766,1242,3,22.92,0,0.0,3
Run Code Online (Sandbox Code Playgroud)
编辑3:文件中的行数74180465
其他则简单pd.read_csv('filename', low_memory=False)
我努力了
from numpy import genfromtxt
my_data = genfromtxt('data/train.csv', delimiter=',')
Run Code Online (Sandbox Code Playgroud)
更新 下面的代码刚刚工作,但我仍然想弄清楚这个问题的根源,一定有什么问题。
import pandas as pd
import gc
data = pd.DataFrame()
data_iterator = pd.read_csv('data/train.csv', chunksize=100000)
for sub_data in data_iterator:
data.append(sub_data)
gc.collect()
Run Code Online (Sandbox Code Playgroud)
编辑:一段有效的代码。 感谢所有帮助人员,我通过添加 python 数据类型而不是 numpy 数据类型搞乱了我的数据类型。一旦我修复了下面的代码就可以正常工作。
dtypes = {'Semana': pd.np.int8,
'Agencia_ID':pd.np.int8,
'Canal_ID':pd.np.int8,
'Ruta_SAK':pd.np.int8,
'Cliente_ID':pd.np.int8,
'Producto_ID':pd.np.int8,
'Venta_uni_hoy':pd.np.int8,
'Venta_hoy':pd.np.float16,
'Dev_uni_proxima':pd.np.int8,
'Dev_proxima':pd.np.float16,
'Demanda_uni_equil':pd.np.int8}
data = pd.read_csv('data/train.csv', dtype=dtypes)
Run Code Online (Sandbox Code Playgroud)
这将内存消耗降低到略低于 4Gb
作为文本存储在内存中的文件不像压缩的二进制格式那么紧凑,但它在数据方面相对紧凑。如果是一个简单的ascii文件,除了任何文件头信息之外,每个字符只有1个字节。Python 字符串也有类似的关系,其中内部 Python 内容会产生一些开销,但每个额外字符仅添加 1 个字节(通过使用 进行测试__sizeof__)。一旦开始转换为数字类型和集合(列表、数组、数据框等),开销就会增加。例如,列表必须存储每个位置的类型和值,而字符串仅存储值。
>>> s = '3,1110,7,3301,15766,1212,3,25.14,0,0.0,3\r\n'
>>> l = [3,1110,7,3301,15766,1212,3,25.14,0,0.0,3]
>>> s.__sizeof__()
75
>>> l.__sizeof__()
128
Run Code Online (Sandbox Code Playgroud)
一点点测试(假设__sizeof__它是准确的):
import numpy as np
import pandas as pd
s = '1,2,3,4,5,6,7,8,9,10'
print ('string: '+str(s.__sizeof__())+'\n')
l = [1,2,3,4,5,6,7,8,9,10]
print ('list: '+str(l.__sizeof__())+'\n')
a = np.array([1,2,3,4,5,6,7,8,9,10])
print ('array: '+str(a.__sizeof__())+'\n')
b = np.array([1,2,3,4,5,6,7,8,9,10], dtype=np.dtype('u1'))
print ('byte array: '+str(b.__sizeof__())+'\n')
df = pd.DataFrame([1,2,3,4,5,6,7,8,9,10])
print ('dataframe: '+str(df.__sizeof__())+'\n')
Run Code Online (Sandbox Code Playgroud)
返回:
string: 53
list: 120
array: 136
byte array: 106
dataframe: 152
Run Code Online (Sandbox Code Playgroud)