Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find which season a particular date belongs to

Tags:

date

r

I have a vector of dates and for each entry, I would like to assign a season. So for example, if a date is between 21.12. and 21.3., I would says that's winter. So far I have tried the following code but I couldn't make it more generic, irrespective of the year.

my.dates <- as.Date("2011-12-01", format = "%Y-%m-%d") + 0:60 low.date <- as.Date("2011-12-15", format = "%Y-%m-%d") high.date <- as.Date("2012-01-15", format = "%Y-%m-%d")  my.dates[my.dates <= high.date & my.dates >= low.date]   [1] "2011-12-15" "2011-12-16" "2011-12-17" "2011-12-18" "2011-12-19" "2011-12-20" "2011-12-21" "2011-12-22" "2011-12-23" "2011-12-24" "2011-12-25" [12] "2011-12-26" "2011-12-27" "2011-12-28" "2011-12-29" "2011-12-30" "2011-12-31" "2012-01-01" "2012-01-02" "2012-01-03" "2012-01-04" "2012-01-05" [23] "2012-01-06" "2012-01-07" "2012-01-08" "2012-01-09" "2012-01-10" "2012-01-11" "2012-01-12" "2012-01-13" "2012-01-14" "2012-01-15" 

I have tried formatting the dates without the year, but it isn't working.

ld <- as.Date("12-15", format = "%m-%d") hd <- as.Date("01-15", format = "%m-%d") my.dates[my.dates <= hd & my.dates >= ld]  
like image 562
Roman Luštrik Avatar asked Feb 29 '12 13:02

Roman Luštrik


2 Answers

How about using something like this:

getSeason <- function(DATES) {     WS <- as.Date("2012-12-15", format = "%Y-%m-%d") # Winter Solstice     SE <- as.Date("2012-3-15",  format = "%Y-%m-%d") # Spring Equinox     SS <- as.Date("2012-6-15",  format = "%Y-%m-%d") # Summer Solstice     FE <- as.Date("2012-9-15",  format = "%Y-%m-%d") # Fall Equinox      # Convert dates from any year to 2012 dates     d <- as.Date(strftime(DATES, format="2012-%m-%d"))      ifelse (d >= WS | d < SE, "Winter",       ifelse (d >= SE & d < SS, "Spring",         ifelse (d >= SS & d < FE, "Summer", "Fall"))) }  my.dates <- as.Date("2011-12-01", format = "%Y-%m-%d") + 0:60 head(getSeason(my.dates), 24) #  [1] "Fall"   "Fall"   "Fall"   "Fall"   "Fall"   "Fall"   "Fall"   #  [8] "Fall"   "Fall"   "Fall"   "Fall"   "Fall"   "Fall"   "Fall"   # [15] "Winter" "Winter" "Winter" "Winter" "Winter" "Winter" 

One note: 2012 is a good year to which to convert all of the dates; since it is a leap year, any February 29ths in your data set will be handled smoothly.

like image 88
Josh O'Brien Avatar answered Sep 29 '22 13:09

Josh O'Brien


I have something similarly ugly as Tim:

R> toSeason <- function(dat) { +  +     stopifnot(class(dat) == "Date") +  +     scalarCheck <- function(dat) { +         m <- as.POSIXlt(dat)$mon + 1        # correct for 0:11 range +         d <- as.POSIXlt(dat)$mday           # correct for 0:11 range +         if ((m == 3 & d >= 21) | (m == 4) | (m == 5) | (m == 6 & d < 21)) { +             r <- 1 +         } else if ((m == 6 & d >= 21) | (m == 7) | (m == 8) | (m == 9 & d < 21)) { +             r <- 2 +         } else if ((m == 9 & d >= 21) | (m == 10) | (m == 11) | (m == 12 & d < 21)) { +             r <- 3 +         } else { +             r <- 4 +         } +         r +     } +  +     res <- sapply(dat, scalarCheck) +     res <- ordered(res, labels=c("Spring", "Summer", "Fall", "Winter")) +     invisible(res) + } R>  

And here is a test:

R> date <- Sys.Date() + (0:11)*30 R> DF <- data.frame(Date=date, Season=toSeason(date)) R> DF          Date Season 1  2012-02-29 Winter 2  2012-03-30 Spring 3  2012-04-29 Spring 4  2012-05-29 Spring 5  2012-06-28 Summer 6  2012-07-28 Summer 7  2012-08-27 Summer 8  2012-09-26   Fall 9  2012-10-26   Fall 10 2012-11-25   Fall 11 2012-12-25 Winter 12 2013-01-24 Winter R> summary(DF)       Date               Season   Min.   :2012-02-29   Spring:3    1st Qu.:2012-05-21   Summer:3    Median :2012-08-12   Fall  :3    Mean   :2012-08-12   Winter:3    3rd Qu.:2012-11-02               Max.   :2013-01-24              R>  
like image 28
Dirk Eddelbuettel Avatar answered Sep 29 '22 13:09

Dirk Eddelbuettel