9

I have a large set of NetCDF files with historical weather data averaged by month. The time dimension unit is "Days since 1600-01-01" and uses a 360-day calendar. I used the PCICt package to correctly format the time dimension according to the 360-day calendar. My questions are:

  1. I get the following error message when trying to write the data to a data frame or save it to an output file: Error in as.data.frame.default(x[[i]], optional = TRUE) : cannot coerce class ""PCICt"" to a data.frame

  2. Can I extract year and month from this PCICt data?

Any help would be much appreciated.

#packages used
require("PCICt")
require("RNetCDF")

#dput output assigned to "ex" variable (units "Days since 1600-01-01")
ex <- structure(c(1095, 1125, 1155, 1185, 1215, 1245, 1275, 1305, 1335, 
1365, 1395, 1425), .Dim = 12L)

#used PCICt to correctly format date stamp
cal <- "360_day"
origin <- ("1600-01-01")
seconds.per.day <- 86400
origin.pcict <- as.PCICt(origin,cal)
ex_pcict <- origin.pcict + (ex * seconds.per.day)

#result of PCICt code
> print(ex_pcict)
 [1] "1603-01-16" "1603-02-16" "1603-03-16" "1603-04-16"
 [5] "1603-05-16" "1603-06-16" "1603-07-16" "1603-08-16"
 [9] "1603-09-16" "1603-10-16" "1603-11-16" "1603-12-16"

#class definition
> class(ex_pcict)
[1] "PCICt"

#attempt to write to data.frame and resulting error message
> data.frame(date = ex_pcict)
Error in as.data.frame.default(x[[i]], optional = TRUE) : 
  cannot coerce class ""PCICt"" to a data.frame

[SOLVED] After sleeping on my problem, I came to the office this morning and started playing with class conversions, eventually getting a date class with which I could work:

ex_char <- as.character.PCICt(ex_pcict)

ex_date <- as.Date(ex_char)

And then I could write "ex_date" to a data.frame and export as a .txt file. I also used as.numeric(format(ex_date, "%m") and "%Y" to extract month and year, respectively.

jls
  • 224
  • 2
  • 13

1 Answers1

0

Perhaps a tad late with this answer, but there is a new way of dealing with this issue.

CF calendars for climate data

Most climate observation and projection data is formatted using the CF Metadata Conventions, using the time coordinate definition to format the timestamps of the observations/projections. Your data has many hints that this is indeed the case for your data. Nowadays there is package CFtime on CRAN. This package can deal with all CF calendars transparently:

install.packages("CFtime")
library(CFtime)

# Using your example
cf <- CFtime("days from 1600-01-01", "360_day", 
             c(1095, 1125, 1155, 1185, 1215, 1245, 1275, 1305, 1335, 
               1365, 1395, 1425))

# In a CF-compliant file you would read this straight out of your netCDF file
nc <- nc_open("my_data_file.nc")
cf <- CFtime(nc$dim$time$units, nc$dim$time$calendar, nc$dim$time$vals)

# Make a data.frame of the dates as string
data.frame(date = CFtimestamp(cf))

Note that these date strings are not necessarily valid dates on the standard calendar (and thus incompatible with POSIXt and the Date class). A date of 1600-02-30 is valid, while 1600-03-31 is invalid, using the 360_day calendar.

This works on any of the CF calendars, including the standard one. This is quite a bit more straightforward in two lines of code than in your example using the PCICt package.

Why POSIXt is not your friend with CF calendars

There are nine different calendars in the CF conventions and several of these are not compatible with POSIXt: 365_day and noleap don't have any leap days, not even in years like 2016 or 2020; in the 366_day and all_leap calendars EVERY year has a leap day; and finally in the 360_day calendar there are 12 months of 30 days each in every year.

With your dates you don't have a problem because it is always the day in the middle of the month (another CF convention), but with daily data you quickly run into problems. as.character.PCICt() followed by as.Date() will give you a vector of Dates as expected, but it'll have missing days (no 31 January, for instance) and NA values for 29 and 30 February.

Again, the CFtime package will work with these calendars without any data loss.

Why bother?

In the study of the global climate, the interest is typically to identify the change from some baseline. Most studies use 1850 as the baseline year and we currently have about 1.3K of warming globally since that year. Given that global average temperature is about 287K, the relative change that we have observed over about 170 years is 1.3 / 287 = 0.45%. Many studies use much smaller periods of comparison, such as "mid-21st century temperature compared to the baseline period of 1991-2020". Taking the liberty to move a day or two around (as PCICt would do) risks blurring the signal in the data.

Patrick
  • 29,357
  • 6
  • 62
  • 90