将netcdf时间变量转换为R日期对象

Adr*_*ins 5 r unidata netcdf netcdf4

我有一个带有时间序列的netcdf文件,时间变量具有以下典型元数据:

    double time(time) ;
            time:standard_name = "time" ;
            time:bounds = "time_bnds" ;
            time:units = "days since 1979-1-1 00:00:00" ;
            time:calendar = "standard" ;
            time:axis = "T" ;
Run Code Online (Sandbox Code Playgroud)

RI内部想要将时间转换为R日期对象.我通过读取units属性并拆分字符串并使用第三个条目作为我的原点(因此假设间距为"days",时间为00:00等)以硬连线方式实现此目的:

require("ncdf4")
f1<-nc_open("file.nc")
time<-ncvar_get(f1,"time")
tunits<-ncatt_get(f1,"time",attname="units")
tustr<-strsplit(tunits$value, " ")
dates<-as.Date(time,origin=unlist(tustr)[3])
Run Code Online (Sandbox Code Playgroud)

这个硬连线解决方案适用于我的具体示例,但我希望R中可能有一个包很好地处理时间单位的UNIDATA netcdf数据约定并将它们安全地转换为R日期对象?

Adr*_*ins 5

编辑 2023:看来这个包/答案现在已经过时了,请参阅帕特里克接受的答案以获取新的方法。


我刚刚发现(发布问题两年后!)有一个名为ncdf.tools的包,它具有以下功能:

转换日期Ncdf2R

哪个

将 netCDF 文件中的时间向量或自指定原点以来的儒略日(或秒、分钟、小时)向量转换为 POSIXct R 向量。

用法:

convertDateNcdf2R(time.source, units = "days", origin = as.POSIXct("1800-01-01", 
    tz = "UTC"), time.format = c("%Y-%m-%d", "%Y-%m-%d %H:%M:%S", 
    "%Y-%m-%d %H:%M", "%Y-%m-%d %Z %H:%M", "%Y-%m-%d %Z %H:%M:%S"))
Run Code Online (Sandbox Code Playgroud)

论据:

time.source 
Run Code Online (Sandbox Code Playgroud)

数字向量或 netCDF 连接:自起始点以来的多个时间单位或 netCDF 文件连接,在后一种情况下,时间向量是从 netCDF 文件中提取的,该文件,尤其是时间变量,必须遵循 CF netCDF惯例。

units   
Run Code Online (Sandbox Code Playgroud)

字符串:时间源的单位。如果源是 netCDF 文件,则该值将被忽略并从该文件中读取。

origin  
Run Code Online (Sandbox Code Playgroud)

POSIXct 对象:时间源的原点或日/小时零。如果源是 netCDF 文件,则该值将被忽略并从该文件中读取。

因此,只需将 netcdf 连接作为第一个参数传递就足够了,函数会处理其余的事情。警告:只有当 netCDF 文件遵循CF 约定时,这才有效(例如,如果您的单位是“自此后的年数”而不是“自此后的秒数”或“自此后的天数”,则它将失败)。

有关该功能的更多详细信息,请访问: https ://rdrr.io/cran/ncdf.tools/man/convertDateNcdf2R.html

  • 包“ncdf.tools”已存档。相反,现在有一个包“CFtime”,它完全支持 CF 元数据约定“时间”维度。 (2认同)

Pat*_*ick 3

您的希望已通过包裹CFtime得到满足。该包可以无缝处理CF元数据约定“时间”维度,包括所有定义的日历。

f1 <- nc_open("file.nc")
cf <- CFtime(f1$dim$time$units, f1$dim$time$calendar, f1$dim$time$vals)
dates <- CFtimestamp(cf)

# This works reliably only for 3 of the 9 defined calendars
dates <- as.Date(dates)
Run Code Online (Sandbox Code Playgroud)

CFtimestamp()函数为所有可能的日期提供正确的输出,包括“360_day”日历上奇怪的“2023-02-30”,但不包括“2023-03-31”。转换为 POSIXct 很棘手,但您真的需要Date使用 POSIXct 吗?或者字符表示可以很好地工作吗?