Format date-time as seasons in R?

后端 未结 4 1237
夕颜
夕颜 2020-12-04 01:51

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 thi

相关标签:
4条回答
  • 2020-12-04 02:18

    Let Q1 be DJF; Q2, MAM; etc. then:

    seasonal.quarters <- function(x) {
        x <- as.POSIXlt(x)
        x$mon <- (x$mon + 1) %% 12
        quarters(x)
    }
    
    options(stringsAsFactors=FALSE)
    
    nonleap.year <- seq(from=as.POSIXct('2013-1-1'), to=as.POSIXct('2014-1-1'), by='day')
    d <- data.frame(ms=months(nonleap.year), qs=seasonal.quarters(nonleap.year))
    by(d, INDICES=list(d$qs), FUN=function(x) unique(x$ms))
    # : Q1
    # [1] "January"  "February" "December"
    # -------------------------------------
    # : Q2
    # [1] "March" "April" "May"  
    # -------------------------------------
    # : Q3
    # [1] "June"   "July"   "August"
    # -------------------------------------
    # : Q4
    # [1] "September" "October"   "November" 
    
    leap.year <- seq(from=as.POSIXct('2016-1-1'), to=as.POSIXct('2017-1-1'), by='day')
    d <- data.frame(ms=months(leap.year), qs=seasonal.quarters(leap.year))
    by(d, INDICES=list(d$qs), FUN=function(x) unique(x$ms))
    # : Q1
    # [1] "January"  "February" "December"
    # -------------------------------------
    # : Q2
    # [1] "March" "April" "May"  
    # -------------------------------------
    # : Q3
    # [1] "June"   "July"   "August"
    # -------------------------------------
    # : Q4
    # [1] "September" "October"   "November" 
    
    0 讨论(0)
  • 2020-12-04 02:23

    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.

    0 讨论(0)
  • 2020-12-04 02:28

    This is an alternative to 42-'s answer above. Go see my comment there for the reason I posted it.

    dates_orig <- as.POSIXlt(c("2013-01-01", "2013-02-01", "2013-03-01", "2013-04-01", "2013-05-01", "2013-06-01", "2013-07-01", "2013-08-01", "2013-09-01", "2013-10-01", "2013-11-01", "2013-12-01", "2014-01-01", "2014-02-01", "2014-03-01", "2014-04-01", "2014-05-01", "2014-06-01", "2014-07-01", "2014-08-01", "2014-09-01", "2014-10-01", "2014-11-01", "2014-12-01"))
    
    format(dates_orig, format='%Y%b')
     [1] "2013Jan" "2013Feb" "2013Mar" "2013Apr" "2013May" "2013Jun" "2013Jul" "2013Aug" "2013Sep" "2013Oct" "2013Nov" "2013Dec" "2014Jan" "2014Feb" "2014Mar"
    [16] "2014Apr" "2014May" "2014Jun" "2014Jul" "2014Aug" "2014Sep" "2014Oct" "2014Nov" "2014Dec"
    
    dates <- as.POSIXlt(dates_orig)
    # shift Jan and Feb to the previous year
    dates$year[dates$mon < 2] <- dates$year[dates$mon < 2] - 1
    # convert months to seasons (named by first month of season)
    dates$mon <- (((dates$mon - 2) %/% 3) %% 4) * 3 + 2
    
    format(dates, format='%Y%b')
    [1] "2012Dec" "2012Dec" "2013Mar" "2013Mar" "2013Mar" "2013Jun" "2013Jun" "2013Jun" "2013Sep" "2013Sep" "2013Sep" "2013Dec" "2013Dec" "2013Dec" "2014Mar"
    [16] "2014Mar" "2014Mar" "2014Jun" "2014Jun" "2014Jun" "2014Sep" "2014Sep" "2014Sep" "2014Dec"
    
    0 讨论(0)
  • 2020-12-04 02:34

    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.

    0 讨论(0)
提交回复
热议问题