5

I have two dates

begin <- as.Date("2007-05-20")
end   <- as.Date("2010-06-13")

How can I count the days per year?

The output should maybe look like this

year   days
2007   226
2008   366
2009   365
2010   164
speendo
  • 13,045
  • 22
  • 71
  • 107

4 Answers4

11

Let's first create a proper date sequence:

R> bd <- as.Date("2007-05-20")
R> ed <- as.Date("2010-06-13")
R> seqd <- seq(bd, ed, by="1 day")
R> head(seqd)
[1] "2007-05-20" "2007-05-21" "2007-05-22" "2007-05-23" "2007-05-24" "2007-05-25"

We then create a helper function which, given a date, returns its year:

R> getYear <- function(d) as.POSIXlt(d)$year + 1900
R> getYear(head(seqd))
[1] 2007 2007 2007 2007 2007 2007

After that, we just call table() on what the helper returns from the date sequence:

R> table(getYear(seqd))

2007 2008 2009 2010 
 226  366  365  164 
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
2

Or, alternatively create a data.frame with an additional column year (using Dirk's data):

dat = data.frame(seqd, year = strftime(seqd, "%Y"))
> head(dat)
        seqd year
1 2007-05-20 2007
2 2007-05-21 2007
3 2007-05-22 2007
4 2007-05-23 2007
5 2007-05-24 2007
6 2007-05-25 2007

and then use count from the plyr package:

require(plyr)
> count(dat, "year")
  year freq
1 2007  226
2 2008  366
3 2009  365
4 2010  164
Paul Hiemstra
  • 59,984
  • 12
  • 142
  • 149
1

Something like this should do the trick:

function daysPerYear( begin, end )
{
    var days = {};
    for ( var y = begin.getFullYear(); y < end.getFullYear(); y++ )
    {
        days[y] = Math.ceil( ( new Date( y+1, 0, 1 ) - begin ) / 86400000 );
        begin = new Date( y+1, 0, 1 );
    }
    days[ end.getFullYear() ] = Math.ceil( ( end - begin ) / 86400000 );
    return days;
}

Sample:

console.log( daysPerYear( new Date( "2007-05-20" ), new Date( "2010-06-13" ) ) );

http://puu.sh/iBgo

Edit: I thought this was about Javascript.

demongolem
  • 9,474
  • 36
  • 90
  • 105
Overv
  • 8,433
  • 2
  • 40
  • 70
1

A less memory intensive solution would be, albeit not a one liner :)

begin <- as.POSIXlt("2007-05-20", tz = "GMT")
end <- as.POSIXlt("2010-06-13", tz = "GMT")

year <- seq(begin$year, end$year) + 1900
year.begin <- as.POSIXlt(paste(year, "01", "01", sep="-"), tz="GMT")
year.begin[1] <- begin
year.end <- as.POSIXlt(paste(year, "12", "31", sep="-"), tz="GMT")
year.end[length(year.end)] <- end
days <- as.numeric(year.end - year.begin) + 1
cbind(year, days)

Motivated by Make this process more processor intensive and less memory intensive

Community
  • 1
  • 1
Andrei
  • 2,585
  • 1
  • 14
  • 17