Reputation: 601
I would like to have a function month2doty()
in R that, if provided with a number representing a month (e.g. 2
for February), returns a vector containing the day of the year for each day in that month (so 32, 33, 34, …, 59
for February):
> month2doty(2)
[1] 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
Leap years do not exist in my world. I have provided one possible answer below, but I'm sure there are better solutions?
Upvotes: 2
Views: 112
Reputation: 388982
Here is another way to do it in base R. We create a 2-length sequence between the start of the month and the next month and then produce all the dates between them. We use %j
in format
to display the day of the year for those dates.
month2doty <- function(x) {
days <- seq(as.Date(paste0(format(Sys.Date(), "%Y"), "-", x, "-01")),
by = "1 month", length.out = 2)
as.integer(format(seq(days[1], days[2] - 1, by = "day"), "%j"))
}
month2doty(2)
# [1] 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
# 54 55 56 57 58 59
month2doty(12)
# [1] 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
# 354 355 356 357 358 359 360 361 362 363 364 365
Or another variation using seq
only once and days_in_month
from lubridate
library(lubridate)
month2doty <- function(x) {
days <- as.Date(paste0(format(Sys.Date(), "%Y"), "-", x, "-01"))
as.integer(format(seq(days, days + days_in_month(x) - 1, by = "day"), "%j"))
}
If we don't want to treat leap years differently, we can hardcode the year (as in OP)
month2doty <- function(x) {
days <- seq(as.Date(paste0("2015-", x, "-01")), by = "1 month", length.out = 2)
as.integer(format(seq(days[1], days[2] - 1, by = "day"), "%j"))
}
and
month2doty <- function(x) {
days <- as.Date(paste0("2015-", x, "-01"))
as.integer(format(seq(days, days + days_in_month(x) - 1, by = "day"), "%j"))
}
Upvotes: 1
Reputation: 601
My current solution to this the somewhat awkward construction of a lookup table each time the function is called:
month2doty <- function(mon=1){
require(lubridate)
alldays <- seq(from=ymd("2015-01-01"), length.out=365, by="days")
lookuptable <- data.frame(month=month(alldays), day=day(alldays), doty=yday(alldays) )
monthdata <- subset(lookuptable, lookuptable$month==mon)
return(monthdata$doty)
}
month2doty(2)
It works just fine like that, but I wonder if there's a cleaner solution that I'm missing here.
Upvotes: 0