Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Format date-time as seasons in R?

In R, it's possible to format POSIXlt date-time objects as a month:

format(Sys.time(), format='%Y-%m')

Is there a way to do the same thing with seasons, or 3-month groups (DJF, MAM, JJA, SON)? These divisions are really common in climatological and ecological science, and it would be great to have a neat way to format them quickly like with months. Obviously DJF falls over 2 years, but for the purposes or this question, that doesn't really matter - just consistently shove them into either year, (or, ideally, it would be good to be able to specify which year they go into).

I'm using the output as a index for by(), so the output format doesn't matter much, just as long as each year/season is unique.

Edit: example data:

dates <- Sys.Date()+seq(1,380, by=35)
dates <- structure(c(16277, 16312, 16347, 16382, 16417, 16452, 16487, 
                     16522, 16557, 16592, 16627), class = "Date")
dates
#[1] "2014-07-26" "2014-08-30" "2014-10-04" "2014-11-08" "2014-12-13"
# "2015-01-17" "2015-02-21" "2015-03-28" "2015-05-02" "2015-06-06" "2015-07-11"

should result in:

c("2014-JJA", "2014-JJA", "2014-SON", "2014-SON", "2015-DJF", "2015-DJF", 
  "2015-DJF", "2015-MAM", "2015-MAM", "2015-JJA", "2015-JJA")

But the "2015-DJF"s could also be "2014-DJF". Also, the form of the output doesn't matter - "2104q4 or 201404 would also be fine.

like image 222
naught101 Avatar asked Jul 25 '14 02:07

naught101


People also ask

How to format the dates in R?

To format the dates in R, use the format () function. The format () method accepts an R object and the format in which we want the output. The format () method provides you with formatting an R object for pretty printing. The Dates in R are expressed as the number of days since 1970-01-01.

How to get abbreviated weekday from the date in R?

Let’s get today’s date using Sys.Date () method. Now, To get the textual format of this date, use the format () function. The format () method accepts today as R Object and format as the format we want in return. Run the program. To get the abbreviated weekday from the date in R, use the %a.

How to get the date before 1970 in R?

The Dates in R are expressed as the number of days since 1970-01-01. If you want the dates before 1970-01-01, you should use the negative values. If your dates are stored as characters, you have to provide as.Date () function with your vector of dates and the format they are currently stored in.

What is the best date class in R?

Three date/time classes are built-in in R, Date, POSIXct, and POSIXlt. This is the class to use if you have only dates, but no times, in your data. create a vector of dates and find the intervals between them: If you have times in your data, this is usually the best class to use.


2 Answers

as.POSIXlt returns a named list (which makes it unsuitable for data.frame columns). The list columns can be individually accessed and include "year" (1900-based, unlike 1970 used for default) and "mon" (0-based). Best place to see this list in hte help system is ?DateTimeClasses:

First just a Seasons calculation, then a Year-Seasons calculation

 c('DJF', 'MAM', 'JJA', 'SON')[ # select from character vector with numeric vector
          1+((as.POSIXlt(dates)$mon+1) %/% 3)%%4]

 [1] "JJA" "JJA" "SON" "SON" "DJF" "DJF" "DJF" "MAM" "MAM" "JJA"
[11] "JJA"



   paste( 1900 + # this is the base year for POSIXlt year numbering 
             as.POSIXlt( dates )$year + 
             1*(as.POSIXlt( dates )$year==12) ,   # offset needed for December
          c('DJF', 'MAM', 'JJA', 'SON')[          # indexing from 0-based-mon
                             1+((as.POSIXlt(dates)$mon+1) %/% 3)%%4] 
          , sep="-")
 [1] "2014-JJA" "2014-JJA" "2014-SON" "2014-SON" "2014-DJF"
 [6] "2015-DJF" "2015-DJF" "2015-MAM" "2015-MAM" "2015-JJA"
[11] "2015-JJA"

Shouldn't be that difficult to make a function that constructs the formatting you expect. This is just modulo arithmetic on the POSIXlt values for month and year.

like image 164
IRTFM Avatar answered Sep 30 '22 20:09

IRTFM


I like using a lookup vector for these sorts of problems, e.g.:

x <- as.POSIXlt(
  seq.Date(as.Date("2000-01-01"),as.Date("2002-01-01"),by="2 months")
)

E.g., if you want to specify southern hemisphere seasons, you could do:

src <- rep(c("su","au","wi","sp"),each=3)[c(2:12,1)]

paste(format(x,"%Y-%m"),src[x$mon+1])
# [1] "2000-01 su" "2000-03 au" "2000-05 au" "2000-07 wi" "2000-09 sp"
# [6] "2000-11 sp" "2001-01 su" "2001-03 au" "2001-05 au" "2001-07 wi"
#[11] "2001-09 sp" "2001-11 sp" "2002-01 su"

Change the src names as you see fit to relabel the categories.

like image 31
thelatemail Avatar answered Sep 30 '22 18:09

thelatemail