【文件读取】文件太大怎么办?

2022-09-19 10:09:33 浏览数 (1)

关注我们,一起学习~

我们经常会遇到需要读取大文件的情况,比如十几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
代码语言:javascript复制
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

0 人点赞