【问题标题】:R create NetCDF from .CSVR从.CSV创建NetCDF
【发布时间】:2016-03-12 09:51:52
【问题描述】:

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

我有一张这样的表:

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 倍。 我明白为什么,每个维度都有一个矩阵,因为我说过变量是根据经度、纬度和时间。

那么,我将如何导入这种数据,我已经为每次数据采集提供了一个 Lon、Lat、Time 和其他变量?

有人能解释一下吗?

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

【问题讨论】:

    标签: r gis netcdf


    【解决方案1】:

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

    创建维度

    在 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 &lt;- nc_create(f, list(var_temp, var_rh))

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

    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 很少创建一个矩阵并进行单次写入会更快。如果你的数据太大,创建一个额外的数组会超出你的可用内存,你必须结合这两种方法。

    【讨论】:

    • Bueffish,首先,非常感谢您抽出一些时间来帮助我。其次,我非常感谢您明确的答案和示例代码。这对我帮助很大。我正在围绕这个想法跳舞并且有相同的想法,但对解决方案不是很清楚。我主要担心的是给给定维度赋予错误值的可能性。使用startcount 属性值得信赖吗?还是如您所展示的那样使用索引会更合适?这两种方法都非常有效。我将更多地研究无限维度,因为我相信这是需要的。谢谢你,小伙伴。问候
    • 嗨,谢谢你的客气话。我编辑了我的答案,并试图解释一下何时使用什么方法。另请注意,?ncvar_put 是沿无限维度写入 3d 数据的示例。
    • 嗨,再次感谢@Bluefish。您的回答再次帮助清除了一些想法。我读到的关于这个主题的一切现在都更清楚了。再次感谢队友。最好的问候。
    猜你喜欢
    • 1970-01-01
    • 2021-05-25
    • 2021-08-30
    • 2012-05-21
    • 1970-01-01
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 2018-09-14
    相关资源
    最近更新 更多