如何用Python Xarray高效将超大规模NC文件转Excel/CSV?
解决大体积DataFrame转Excel/CSV的高效方案
问题背景
手里有个近3亿行的.nc文件,已经用xarray转成了pandas DataFrame,想转成.xlsx或.csv:
- 直接转xlsx会因为Excel单表最大1048576行的限制报错
- 转CSV的话,文件体积从原400MB膨胀到5-6GB,太占空间
- 想拆分到Excel多个工作表,但不知道怎么高效实现
现有代码
import xarray as xr data = xr.open_dataset('prcp_daily_1948-1948.nc') df = data.to_dataframe() df.to_excel('prcp_daily_1948-1948.xlsx')
报错信息
ValueError: This sheet is too large! Your sheet size is: 316224000, 1 Max sheet size is: 1048576, 16384
高效解决办法
1. 拆分DataFrame到Excel多工作表
利用pandas的ExcelWriter,按Excel单表最大行数拆分数据,分批写入不同工作表。如果内存充足可直接拆分全量DataFrame,内存吃紧的话建议分块读取nc文件:
方式一:直接拆分已生成的DataFrame
import xarray as xr import pandas as pd data = xr.open_dataset('prcp_daily_1948-1948.nc') df = data.to_dataframe() # Excel单表最大行数 max_rows_per_sheet = 1048576 # 计算所需工作表数量 num_sheets = (len(df) // max_rows_per_sheet) + 1 with pd.ExcelWriter('prcp_daily_1948-1948_split.xlsx') as writer: for i in range(num_sheets): start_row = i * max_rows_per_sheet end_row = min((i+1)*max_rows_per_sheet, len(df)) df_chunk = df.iloc[start_row:end_row] df_chunk.to_excel(writer, sheet_name=f'Sheet{i+1}')
方式二:分块读取nc文件(低内存占用)
import xarray as xr import pandas as pd max_rows_per_sheet = 1048576 chunk_size = max_rows_per_sheet # 分块加载nc文件 ds = xr.open_dataset('prcp_daily_1948-1948.nc', chunks={'time': chunk_size}) with pd.ExcelWriter('prcp_daily_1948-1948_split.xlsx') as writer: sheet_num = 1 # 按分块逐个写入工作表 for chunk in ds.to_dataframe().groupby(pd.Grouper(level='time', sort=False)).chunk(chunk_size): chunk.to_excel(writer, sheet_name=f'Sheet{sheet_num}') sheet_num += 1
2. 压缩CSV减少体积
如果可以接受CSV格式,直接保存为压缩格式(如gzip),能大幅降低文件体积,pandas原生支持:
import xarray as xr data = xr.open_dataset('prcp_daily_1948-1948.nc') df = data.to_dataframe() # 保存为gzip压缩的CSV,体积接近原nc文件大小 df.to_csv('prcp_daily_1948-1948.csv.gz', compression='gzip')
读取时直接用pd.read_csv('prcp_daily_1948-1948.csv.gz')即可,无需手动解压。
3. 使用列式存储格式(推荐)
如果不是必须用Excel/CSV,推荐用Parquet格式——专为大数据设计的列式存储,压缩率高、读写速度快,xarray可直接转换:
import xarray as xr data = xr.open_dataset('prcp_daily_1948-1948.nc') # 直接将nc转存为Parquet data.to_parquet('prcp_daily_1948-1948.parquet') # 读取时直接加载: # data = xr.open_dataset('prcp_daily_1948-1948.parquet', engine='pyarrow')
这种格式体积通常比原nc文件更小,后续数据分析效率也更高,完全避开Excel行数限制和CSV体积问题。
内容的提问来源于stack exchange,提问作者piseynir
相关产品推荐
相关产品推荐

