关注我们,一起学习~
我们经常会遇到需要读取大文件的情况,比如十几GB,几十GB甚至更大,而如果直接读取进来,内存可能会爆炸,溢出。笔者最近遇到读取大文件的情况,借此和大家分享一些读取大文件的方法。
open
一行一行读,一行一行执行对应的操作
代码语言:javascript复制freader = open(filename, 'rb')
while True:
try:
line = freader.readline()
# do some work
except StopIteration:
break
pandas
分块读
代码语言:javascript复制import pandas as pd
reader = pd.read_csv(filename, iterator=True)
# 每次读取size大小的块,返回的是dataframe
data = reader.get_chunk(size)
修改列的类型
改变每一列的类型,从而减少存储量
- 对于label或者类型不多的列(如性别,0,1,2),默认是int64的,可以将列的类型转换为int8
- 对于浮点数,默认是float64,可以转换为float32
- 对于类别型的列,比如商品ID,可以将其编码为category
import pandas as pd
reader = pd.read_csv(filename, iterator=True)
data = reader.get_chunk(size)
# downcast用于修改类型,
# errors为当无法转换或遇到错误是采用什么操作,
# 可以采用raise(报错),ignore(忽略),coerce转为NaN
data[column_name1] = pd.to_numeric(data[column_name], downcast='unsigned', errors='coerce')
data[column_name2] = pd.to_numeric(data[column_name], downcast='float', errors='coerce')
data[column_name3] = data[column_name3].astype('category')
例子
代码语言:javascript复制reader = pd.read_csv('./cygg/train_data.txt', iterator=True, header=None)
arr = []
for i in range(10):
data = reader.get_chunk(100000)
data.columns = [str(i) for i in range(246)]
arr.append(data)
data = pd.concat(arr)
# 计算原始数据大小GB
print(data.memory_usage().sum()/(1024**3))
# 将label的int64转变为int8
data['0'] = pd.to_numeric(data['0'], downcast='unsigned', errors='coerce')
# 计算转变后的数据大小GB
print(data.memory_usage().sum()/(1024**3))
# 将float64转变为float32
for i in range(6, 246):
data[str(i)] = pd.to_numeric(data[str(i)], downcast='float', errors='coerce')
# 计算转变后的大小GB
print(data.memory_usage().sum()/(1024**3))
# 将类别型变量转变为category类型
for i in range(1, 6):
data[str(i)] = data[str(i)].astype('category')
print(data.memory_usage().sum()/(1024**3))
原始大小:1.8328GB,转int8后:1.8263GB,转float32后:0.9323GB,转category后:0.9037GB 可以发现修改类型后,内存的消耗大幅缩减了
参考
https://zhuanlan.zhihu.com/p/34420427