如何处理大小超过30 GiB、格式为SAS7BDAT的大型数据集?
方案1:使用pandas内置分块读取(零额外依赖,新手首选)
pandas的pd.read_sas()本身支持分块加载,不用把整个文件一次性塞到内存里,适合只需要做简单统计、过滤、逐批处理数据的场景。
具体操作代码:
import pandas as pd # 配置单批次读取的行数,根据自己的内存大小调整,16G内存可以设为10万行,8G设为5万行 chunk_size = 100000 # 目标sas文件路径 file_path = "你的文件路径/xxx.sas7bdat" # 初始化结果存储,比如你要统计某列的总和,或者过滤符合条件的行 filtered_data = [] # 逐块读取 for chunk in pd.read_sas(file_path, chunksize=chunk_size, encoding='你的文件编码,常见的有gbk、utf-8、latin-1'): # 这里写你要对每块数据做的操作,比如过滤出某列大于100的行 temp = chunk[chunk['目标列名'] > 100] filtered_data.append(temp) # 最后把所有过滤后的小块合并,这时候合并后的大小一般远小于原文件,不会爆内存 final_result = pd.concat(filtered_data, ignore_index=True)
注意点:
- 编码如果不确定可以先读10行测试,比如先设
chunksize=10,读一块看有没有乱码,调整encoding参数 - 如果是要做全量聚合(比如求全年的均值、总和),可以逐块计算中间结果,最后再合并中间结果,不用存所有块的数据
方案2:用Dask处理(代码改动最少,适合类pandas操作)
Dask可以模拟pandas的接口,自动后台分块处理大文件,不用自己写循环逻辑,适合需要用pandas常用函数但不想改太多代码的场景。
首先安装依赖:pip install dask[sas]
具体操作代码:
import dask.dataframe as dd # 直接读sas文件,dask会自动分块,不会加载全量到内存 ddf = dd.read_sas("你的文件路径/xxx.sas7bdat", encoding='文件编码', chunksize='1GB') # 可以指定每个块的大小 # 所有操作和pandas几乎一致,比如过滤、统计 # 例子:筛选某列为特定值,再按日期分组求和 result = ddf[ddf['分类列'] == '目标分类'].groupby('日期列')['数值列'].sum() # 最后调用compute()才会实际执行计算,返回pandas的DataFrame final_result = result.compute()
注意点:
- 如果要处理多个sas文件,直接把路径换成列表就行,比如
dd.read_sas(["file1.sas7bdat", "file2.sas7bdat"], ...),dask会自动合并处理 - 不要随意调用
ddf.compute(),会把全量数据加载到内存,只有做完过滤、聚合等缩小数据量的操作后再调用compute
方案3:导入本地SQLite数据库(适合反复查询场景)
如果需要经常对这批数据做不同维度的查询,导入本地SQLite是最灵活的方式,SQLite是文件型数据库,不用装额外服务端。
具体操作步骤:
- 逐块读取sas文件,写入SQLite
import pandas as pd import sqlite3 # 连接本地SQLite数据库,没有会自动创建 conn = sqlite3.connect('sas_data.db') chunk_size = 100000 file_path = "你的文件路径/xxx.sas7bdat" for chunk in pd.read_sas(file_path, chunksize=chunk_size, encoding='文件编码'): # 逐块写入表,表名自己定义,比如year_data chunk.to_sql('year_data', conn, if_exists='append', index=False) # 所有数据写完后关闭连接 conn.close()
- 后续需要用数据的时候,直接用SQL查询想要的部分就行,不用读全量:
conn = sqlite3.connect('sas_data.db') # 写SQL语句取你需要的部分,比如取2023年6月的所有数据 query = "SELECT * FROM year_data WHERE 日期列 BETWEEN '2023-06-01' AND '2023-06-30'" df = pd.read_sql(query, conn) conn.close()
内容的提问来源于stack exchange,提问作者Adeib Bashar
相关产品推荐
相关产品推荐

