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.
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With