Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

convert a netcdf time variable to an R date object

I have a netcdf file with a timeseries and the time variable has the following typical metadata:

    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" ;

Inside R I want to convert the time into an R date object. I achieve this at the moment in a hardwired way by reading the units attribute and splitting the string and using the third entry as my origin (thus assuming the spacing is "days" and the time is 00:00 etc):

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])

This hardwired solution works for my specific example, but I was hoping that there might be a package in R that nicely handles the UNIDATA netcdf date conventions for time units and convert them safely to an R date object?

like image 202
Adrian Tompkins Avatar asked Sep 01 '17 13:09

Adrian Tompkins


People also ask

Does R have a time data type?

In addition to the time data types R also has a date data type. The difference is that the date data type keeps track of numbers of days rather than seconds. You can cast a string into a date type using the as. Date function.

How do I convert NC data to CSV?

xarray usage to convert netcdf to csv We open the netcdf file (using open_dataset() method), convert it to a dataframe ( to_dataframe() method) and write this object to a csv file ( to_csv() method).


1 Answers

I have just discovered (two years after posting the question!) that there is a package called ncdf.tools which has the function:

convertDateNcdf2R

which

converts a time vector from a netCDF file or a vector of Julian days (or seconds, minutes, hours) since a specified origin into a POSIXct R vector.

Usage:

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"))

Arguments:

time.source 

numeric vector or netCDF connection: either a number of time units since origin or a netCDF file connection, In the latter case, the time vector is extracted from the netCDF file, This file, and especially the time variable, has to follow the CF netCDF conventions.

units   

character string: units of the time source. If the source is a netCDF file, this value is ignored and is read from that file.

origin  

POSIXct object: Origin or day/hour zero of the time source. If the source is a netCDF file, this value is ignored and is read from that file.

Thus it is enough to simply pass the netcdf connection as the first argument and the function handles the rest. Caveat: This will only work if the netCDF file follows CF conventions (e.g. if your units are "years since" instead of "seconds since" or "days since" it will fail for example).

More details available here: https://rdrr.io/cran/ncdf.tools/man/convertDateNcdf2R.html

like image 84
Adrian Tompkins Avatar answered Sep 18 '22 22:09

Adrian Tompkins