R 从 .CSV 创建 NetCDF

R create NetCDF from .CSV

我正在尝试从 .csv 文件创建 NetCDF。我已经在这里和其他地方阅读了几个教程,但仍然有一些疑问。

我有一个 table 根据这个:

lat,long,time,rh,temp
41,-109,6,1,1
40,-107,18,2,2
39,-105,6,3,3
41,-103,18,4,4
40,-109,6,5,2
39,-107,18,6,4

我使用 R 中的 ncdf4 包创建了 NetCDF。

xvals <- data$lon
yvals <- data$lat 
nx <- length(xvals)
ny <- length(yvals)
lon1 <- ncdim_def("longitude", "degrees_east", xvals)
lat2 <- ncdim_def("latitude", "degrees_north", yvals)
time <- data$time
mv <- -999 #missing value to use

var_temp <- ncvar_def("temperatura", "celsius", list(lon1, lat2, time), longname="Temp. da superfície", mv) 

var_rh <- ncvar_def("humidade", "%", list(lon1, lat2, time), longname = "humidade relativa", mv )

ncnew <- nc_create(filename, list(var_temp, var_rh))
ncvar_put(ncnew, var_temp, dadostemp, start=c(1,1,1), count=c(nx,ny,nt))

当我按照程序进行操作时,它指出 NC 期望的数据数量是我拥有的数据数量的 3 倍。 我明白为什么,每个维度一个矩阵,因为我说变量是根据经度、纬度和时间。

那么,我如何导入这种数据,我已经为每个数据采集一个经度、纬度、时间和其他变量?

有人能解释一下吗?

PS: 这里使用的数据不是我的真实数据,只是我在教程中使用的一些例子。

我认为您的代码中存在不止一个问题。一步一步:

创建维度

在 nc 文件中,维度不能用作键值,只有一个值向量定义变量数组中每个位置的含义。 这意味着您应该像这样创建维度:

xvals <- unique(data$lon)
xvals <- xvals[order(xvals)]
yvals <- yvals[order(unique(data$lat))] 
lon1 <- ncdim_def("longitude", "degrees_east", xvals)
lat2 <- ncdim_def("latitude", "degrees_north", yvals)
time <- data$time
time_d <- ncdim_def("time","h",unique(time))

在我工作的地方,我们使用无限维度作为单纯的索引,而与维度同名的一维变量保存值。我不确定无限维度在 R 中是如何工作的。因为你不要求它,所以我把它省略了:-)

定义变量

mv <- -999 #missing value to use
var_temp <- ncvar_def("temperatura", "celsius", 
                      list(lon1, lat2, time_d), 
                      longname="Temp. da superfície", mv) 
var_rh <- ncvar_def("humidade", "%", 
                     list(lon1, lat2, time_d), 
                     longname = "humidade relativa", mv )

添加数据

创建 nc 文件:ncnew <- nc_create(f, list(var_temp, var_rh))

当添加值时,保存数据的对象被熔化为一维数组,并在 start 指定的位置开始顺序写入。要写入的维度由计数中的值控制。如果你有这样的数据:

long, lat, time, t
   1,   1,    1, 1
   2,   1,    1, 2
   1,   2,    1, 3
   2,   2,    1, 4

命令 ncvar_put(ncnew, var_temp,data$t,count=c(2,2,1)) 会给你(可能)期望的结果。

对于您的数据,第一步是为维度创建索引:

data$idx_lon <- match(data$long,xvals)
data$idx_lat <- match(data$lat,yvals)
data$idx_time <- match(data$time,unique(time))

然后创建一个维度适合您的数据的数组:

m <- array(mv,dim = c(length(yvals),length(xvals),length(unique(time))))

然后用您的值填充数组:

for(i in 1:NROW(data)){
  m[data$idx_lat[i],data$idx_lon[i],data$idx_time[i]] <- data$temp[i]
}

如果速度是一个问题,您可以计算向量化的线性索引并将其用于赋值。

写入数据

ncvar_put(ncnew, var_temp,m)

请注意,您不需要 startcount

最后关闭nc文件写入数据到磁盘nc_close(ncnew) (可选)我建议您使用 ncdump 控制台命令来检查您的文件。

编辑

关于你的问题是写一个完整的数组还是使用startcount我相信这两种方法都可靠。更喜欢哪一个取决于您的数据和您的个人喜好。

我觉得建一个数组,把值相加,然后写成一个整体的方法比较好理解。但是,当询问什么更有效时,它取决于数据。如果您的数据很大并且有很多 NA 值,我相信使用带有 start 和 count 的多次写入可能会更快。如果 NA 很少见,则创建一个矩阵并进行单次写入会更快。如果你的数据太大,创建一个额外的数组会超出你的可用内存,你必须结合这两种方法。