You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Xarray将含三维变量的CSV转换为NetCDF文件

解决CSV转三维NetCDF(维度time, lat, lon)的问题

我需要把包含year、lat、lon、pressure字段的CSV转换成三维NetCDF文件,要求pressure变量的维度为(time, lat, lon)。但CSV的结构是每个(year, lon, lat)组合对应一个pressure值,示例如下:

year,lon,lat,pressure
1/1/00,79.4939,34.4713,11981569640
1/1/01,79.4939,34.4713,11870476671
1/1/02,79.4939,34.4713,11858633008
1/1/00,77.9513,35.5452,11254617090
1/1/01,77.9513,35.5452,11267424230
1/1/02,77.9513,35.5452,11297377976
1/1/00,77.9295,35.5188,1031160490

我的尝试与问题

最初直接尝试转换,代码如下:

import pandas as pd
import xarray as xr
csv_file = '.csv'
df = pd.read_csv(csv_file)
df = df.set_index(["year", "lon", "lat"])
xr = df.to_xarray()
nc=xr.to_netcdf('netcdf.nc')

之后尝试相关方法但未成功,我认为需要先把CSV结构整理成唯一经纬度对应多时间点pressure的形式,期望结构如下:

longitude,latitude,1/1/2000,1/1/2001,1/1/2002....
79.4939,34.4713,11981569640,...
77.9513,35.5452,11254617090,... 
77.9295,35.5188,1031160490,... 

试过用pd.melt转换,但写法有误:

df = pd.melt(df, id_vars=["year","lon", "lat"], var_name="year", value_name="PRESSURE")

我的目标是实现类似以下代码的效果(但原代码无法正确生成三维结构):

filename = '13.csv'
colnames = ['year','lon','lat','pressure']
df = pd.read_csv(filename, names = colnames)

df["year"]= pd.to_datetime(df["year"], errors='coerce') 
xr = df.set_index(['year','lon','lat']).to_xarray()

#xr['time'].attrs={'units':'hours since 2018-01-01'}
xr['lat'].attrs={'units':'degrees', 'long_name':'Latitude'}
xr['lon'].attrs={'units':'degrees', 'long_name':'Longitude'}
xr['pressure'].attrs={'units':'pa', 'long_name':'Pressure'}

xr.to_netcdf('my_netcdf.nc')

正确解决方案

步骤1:读取并预处理数据

先读取CSV,将year转为datetime类型,确保时间维度解析正确:

import pandas as pd
import xarray as xr

filename = '13.csv'
df = pd.read_csv(filename)
# 转换year为datetime,格式匹配CSV中的月/日/两位年
df['year'] = pd.to_datetime(df['year'], format='%m/%d/%y')

步骤2:长表转宽表(核心操作)

使用pivot将长格式数据转为宽格式,让每个经纬度组合对应所有时间的pressure值:

# 以lon、lat为索引,year为列,pressure为值重塑数据
df_wide = df.pivot(index=['lon', 'lat'], columns='year', values='pressure')
# 重置索引,让lon、lat回到列便于后续转换
df_wide = df_wide.reset_index()

步骤3:转换为xarray并调整维度

将宽表转为xarray Dataset,整合时间列为time维度,并调整维度顺序为(time, lat, lon):

# 转为xarray Dataset
ds = xr.Dataset.from_dataframe(df_wide.set_index(['lon', 'lat']))
# 将时间列转为统一的time维度
ds = ds.to_array(name='pressure').transpose('time', 'lat', 'lon')

# 添加变量属性
ds['lat'].attrs={'units':'degrees', 'long_name':'Latitude'}
ds['lon'].attrs={'units':'degrees', 'long_name':'Longitude'}
ds['pressure'].attrs={'units':'pa', 'long_name':'Pressure'}
ds['time'].attrs={'long_name':'Time'}

步骤4:保存为NetCDF

ds.to_netcdf('my_netcdf.nc')

关键说明

  1. 方法选择错误:之前用pd.melt是宽表转长表,而我们需要的是长表转宽表,pivot才是正确方法。
  2. 维度调整:转换为xarray后,需要通过transpose将维度顺序调整为目标的(time, lat, lon)。
  3. 日期解析:如果CSV中的日期格式不同,需调整pd.to_datetime的format参数确保解析正确。

内容的提问来源于stack exchange,提问作者HLGNT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:10:31