I want to generate a sequence of dates with one quarter interval, with a starting date and ending date. I have below code :
> seq(as.Date('1980-12-31'), as.Date('1985-06-30'), by = 'quarter')
[1] "1980-12-31" "1981-03-31" "1981-07-01" "1981-10-01" "1981-12-31"
[6] "1982-03-31" "1982-07-01" "1982-10-01" "1982-12-31" "1983-03-31"
[11] "1983-07-01" "1983-10-01" "1983-12-31" "1984-03-31" "1984-07-01"
[16] "1984-10-01" "1984-12-31" "1985-03-31"
As you can see, this is not generating right sequence, as I dont understand how the date "1981-07-01" is coming here, I would expect "1981-06-30".
Is there any way to generate such sequence correctly with quarter interval?
Thanks for your time.
The from and to dates in the question are both end-of-quarter dates so we assume that that is the general case you are interested in.
1) Create a sequence of yearqtr objects yq and then convert them to Date class. frac=1 tells it s to use the end of the month. Alternately just use yq since that directly models years with quarters.
library(zoo)
from <- as.Date('1980-12-31')
to <- as.Date('1985-06-30')
yq <- seq(as.yearqtr(from), as.yearqtr(to), by = 1/4)
as.Date(yq, frac = 1)
giving;
[1] "1980-12-31" "1981-03-31" "1981-06-30" "1981-09-30" "1981-12-31"
[6] "1982-03-31" "1982-06-30" "1982-09-30" "1982-12-31" "1983-03-31"
[11] "1983-06-30" "1983-09-30" "1983-12-31" "1984-03-31" "1984-06-30"
[16] "1984-09-30" "1984-12-31" "1985-03-31" "1985-06-30"
2) or without any packages add 1 to from and to so that they are at the beginning of the next month, create the sequence (it has no trouble with first of month sequences) and then subtract 1 from the generated sequence giving the same result as above.
seq(from + 1, to + 1, by = "quarter") - 1
Using the clock package and R >= 4.1:
library(clock)
seq(year_quarter_day(1980, 4), year_quarter_day(1985, 2), by = 1) |>
set_day("last") |>
as_date()
# [1] "1980-12-31" "1981-03-31" "1981-06-30" "1981-09-30" "1981-12-31" "1982-03-31" "1982-06-30" "1982-09-30" "1982-12-31"
# [10] "1983-03-31" "1983-06-30" "1983-09-30" "1983-12-31" "1984-03-31" "1984-06-30" "1984-09-30" "1984-12-31" "1985-03-31"
# [19] "1985-06-30"
Note that this includes the final quarter. I don't know if that was your intent.
Different definition of "quarter". A quarter might well be (although it is not in R) 365/4 days. Look at output of :
as.Date('1980-12-31')+(365/4)*(0:12)
#[1] "1980-12-31" "1981-04-01" "1981-07-01" "1981-09-30" "1981-12-31" "1982-04-01" "1982-07-01" "1982-09-30"
#[9] "1982-12-31" "1983-04-01" "1983-07-01" "1983-09-30" "1983-12-31"
In order to avoid the days of the month from surprising you, you need to use a starting day of the month between 1 and 28, at least in non-leap years.
seq(as.Date('1981-01-01'), as.Date('1985-06-30'), by = 'quarter')
[1] "1981-01-01" "1981-04-01" "1981-07-01" "1981-10-01" "1982-01-01" "1982-04-01" "1982-07-01" "1982-10-01"
[9] "1983-01-01" "1983-04-01" "1983-07-01" "1983-10-01" "1984-01-01" "1984-04-01" "1984-07-01" "1984-10-01"
[17] "1985-01-01" "1985-04-01"
Related
I am trying to subtract 3 months from February to a date using lubridate library, however, it always gives me date as 28. I know a lot of people have asked this question, but I have tried a lot of things, but still the same error. Looping through the day is an option. However, I was looking for something efficient
what my code does is this:
where test_end = "2019-02-28"
and lastnmonth = 3
as.Date(test_end) %m-% months(lastnmonth)
I always get the output as "2018-11-28" instead of "2018-11-30"
lubridate::ymd("2019-02-28") - lubridate::period(3, "months")
additional code to work-out mont-end
lubridate::ceiling_date(lubridate::ymd("2019-02-28") - lubridate::period(3, "months"), "months") - lubridate::ddays(1)
You want the last of the month -- so you can use the trick that the next is a first, move that one by the number of months -- and then substract one day.
All in one line of base R:
R> seq(as.Date("2019-02-28") + 1, length=4, by="-1 month") - 1
[1] "2019-02-28" "2019-01-31" "2018-12-31" "2018-11-30"
R>
We add one day, then use a sequence of four months (including current) backwards, and take out one day to be on the last day of the previous month.
If you just want one, simply add tail(..., 1):
R> tail(seq(as.Date("2019-02-28") + 1, length=4, by="-1 month") - 1, 1)
[1] "2018-11-30"
R>
Using Dirk's strategy we can draw-up a function to handle this type of operation:
start_date <- lubridate::ymd("2019-02-28")
mths_to_subtract <- 3
deduct_mth <- function(date_object = start_date,
mths_to_deduct = mths_to_subtract){
days_to_ceiling_date <- lubridate::ceiling_date(date_object, "months") - date_object
date_object + days_to_ceiling_date - lubridate::period(mths_to_deduct, "months") - days_to_ceiling_date
}
Gives the following answers:
> deduct_mth(ymd("2019-02-28"), 3)
[1] "2018-11-30"
> deduct_mth(ymd("2000-02-29"), 3)
[1] "1999-11-30"
Good afternoon. I am attempting to make a sequence of month-day dates. The desired result would be October 1st through December 31st. I think the code is simple enough to show my intent, but is flawed in its logic. Thanks very much for any help here.
start <- as.Date("10/1", "m%-d%")
end <- as.Date("12/31", "m%-d%")
seq(start, end, by = "1 Day")
We can create a date sequence (any year would work, no need to be 2001 in my example), and then use the format function.
format(seq.Date(as.Date("2001-10-31"), as.Date("2001-12-31"), by = 1),
format = "%m-%d")
# [1] "10-31" "11-01" "11-02" "11-03" "11-04" "11-05" "11-06" "11-07" "11-08" "11-09" "11-10"
# [12] "11-11" "11-12" "11-13" "11-14" "11-15" "11-16" "11-17" "11-18" "11-19" "11-20" "11-21"
# [23] "11-22" "11-23" "11-24" "11-25" "11-26" "11-27" "11-28" "11-29" "11-30" "12-01" "12-02"
# [34] "12-03" "12-04" "12-05" "12-06" "12-07" "12-08" "12-09" "12-10" "12-11" "12-12" "12-13"
# [45] "12-14" "12-15" "12-16" "12-17" "12-18" "12-19" "12-20" "12-21" "12-22" "12-23" "12-24"
# [56] "12-25" "12-26" "12-27" "12-28" "12-29" "12-30" "12-31"
Alternatively with lubridate:
library(lubridate)
format( seq(ymd('2018-10-01'),ymd('2018-12-31'),by='days'), "%m-%d" )
[1] "10-01" "10-02" "10-03" "10-04" "10-05" "10-06" "10-07" "10-08" "10-09"
...etc to "12-31"
I have continuous daily data from 2015-12-01 to 2016-07-01.Since it's already been aggregated, these are unique dates with correspondent quantity.
However, whenever i convert the data into time series using ts() and plot.ts() it. The potting shows my tseries never reach 2016-07-01, but only stops around 2016-0. While ggplot of df data shows the ideal graph.
df
tseries = ts(df$F, start = c(2015,12,01), end = c(2016,07,01), frequency = 208)
plot.ts(tseries)
tseries
dfplotting
tldr; You misspecified the frequency (and start) arguments in ts; either provide correct frequency/start arguments, or use the zoo package instead.
There is a misunderstanding about the role of frequency in ts. The frequency argument depends on the format of your data. For example, if you have daily data for a year then frequency would be 365, since one year has 365 days (ignoring leap years). start then has to match the frequency of your data. For daily data, start needs to provide the day (out of 365) of your start date.
Let's generate a date sequence from 01/12/2015 until 01/07/2016 in 1 day steps.
dates <- seq(as.Date("2015/12/01"), as.Date("2016/07/01"), by = "1 day")
Next we generate some sample data for every day.
set.seed(2017);
x <- 100 - cumprod(1 + rnorm(length(dates), 0.01, 0.05))
We create a ts object and plot.
tseries <- ts(
x,
start = c(2015, as.numeric(format(dates[1], "%j"))),
frequency = 365)
plot.ts(tseries);
Note how as.numeric(format(dates[1], "%j")) is the day of the year that corresponds to the 01/12/2015; we can inspect tseries to confirm
tseries;
#Time Series:
#Start = c(2015, 335)
#End = c(2016, 183)
#Frequency = 365
# [1] 98.91829 98.91165 98.86055 98.94935 98.94251 98.90804 99.00404 98.99416
# [9] 98.99744 98.90906 98.87945 98.78015 98.81349 98.78344 98.85828 98.77868
# [17] 98.79591 98.70452 98.76475 98.80961 98.78934 98.82882 98.70564 98.79937
# [25] 98.74176 98.72526 98.73731 98.68448 98.72841 98.70941 98.74059 98.71282
# [33] 98.66201 98.71089 98.67883 98.45837 98.52216 98.36389 98.37027 98.37203
# [41] 98.44200 98.42452 98.46624 98.52957 98.53985 98.44419 98.42480 98.33157
# [49] 98.23825 98.11436 97.96746 98.10811 98.07050 98.05331 98.18894 98.26369
# [57] 98.10984 97.95076 97.95309 97.96750 97.86906 97.82784 97.95063 97.92361
# [65] 97.80495 97.75671 97.78848 97.70829 97.60183 97.67609 97.51230 97.57353
# [73] 97.62052 97.79321 97.57016 97.18006 97.25852 97.25187 97.13964 97.10216
# [81] 97.44889 97.22116 97.20823 97.16990 97.13855 97.10450 96.93565 96.79920
# [89] 96.82153 96.84342 96.86261 96.78734 97.08032 97.19380 97.30147 97.21610
# [97] 97.23463 97.39229 97.47829 97.56498 97.53851 97.34443 97.32700 97.18775
#[105] 97.29549 97.53480 97.44546 97.38659 97.23025 97.29599 97.36905 97.38267
#[113] 97.30787 97.36199 97.41452 97.31361 96.98821 96.92238 96.78418 96.87618
#[121] 96.78397 96.79244 96.80496 96.87619 97.00473 96.77162 96.61101 96.91671
#[129] 96.70001 96.75187 96.85348 96.77186 96.59937 96.72491 96.81188 96.80928
#[137] 96.71012 96.39952 96.49581 96.50415 96.56627 96.51843 96.72303 96.59825
#[145] 96.71873 96.65840 96.69296 96.86833 96.79887 96.71224 96.75685 96.76380
#[153] 96.63228 96.74893 96.51374 96.66589 96.61319 96.75718 96.62919 96.39169
#[161] 96.47066 96.59940 96.52173 96.50408 96.22667 96.03279 96.01529 95.80778
#[169] 95.77858 95.90350 96.15438 95.86239 95.99304 95.89340 95.70911 95.74620
#[177] 95.66125 95.81266 95.56044 95.36743 95.35368 95.54013 95.17587 95.07042
#[185] 94.67955 94.57888 94.57412 94.37998 94.36650 93.92591 93.82484 93.71398
#[193] 93.66040 93.60182 93.51263 93.54927 92.93701 92.72238 92.63081 92.85764
#[201] 92.61470 92.28663 92.28687 92.17086 92.31845 92.11827 91.72824 91.78567
#[209] 91.68942 91.34734 90.89702 91.32072 91.11538 90.83474
Note that the 335th day of 2015 corresponds to the 1st of December 2015, and the 183rd day of 2016 to the 1st of July 2016.
As an alternative we can also use the zoo package, which has the benefit that we don't have to work out the proper frequency (and start) arguments.
library(zoo);
tseries <- zoo(x, dates);
plot.zoo(tseries);
This question already has answers here:
Get Dates of a Certain Weekday from a Year in R
(3 answers)
Closed 9 years ago.
I would like to generate a dataframe that contains all the Friday dates for the whole year.
Is there a simple way to do this?
eg for December 2013: (6/12/13,13/12/13,20/12/13,27/12/13)
Thank you for your help.
I'm sure there is a simpler way, but you could brute force it easy enough:
dates <- seq.Date(as.Date("2013-01-01"),as.Date("2013-12-31"),by="1 day")
dates[weekdays(dates)=="Friday"]
dates[format(dates,"%w")==5]
Building on #Frank's good work, you can find all of any specific weekday between two dates like so:
pick.wkday <- function(selday,start,end) {
fwd.7 <- start + 0:6
first.day <- fwd.7[as.numeric(format(fwd.7,"%w"))==selday]
seq.Date(first.day,end,by="week")
}
start and end need to be Date objects, and selday is the day of the week you want (0-6 representing Sunday-Saturday).
i.e. - for the current query:
pick.wkday(5,as.Date("2013-01-01"),as.Date("2013-12-31"))
Here is a way.
d <- as.Date(1:365, origin = "2013-1-1")
d[strftime(d,"%A") == "Friday"]
Alternately, this would be a more efficient approach for generating the data for an arbitrary number of Fridays:
wk1 <- as.Date(seq(1:7), origin = "2013-1-1") # choose start date & make 7 consecutive days
wk1[weekdays(wk1) == "Friday"] # find Friday in the sequence of 7 days
seq.Date(wk1[weekdays(wk1) == "Friday"], length.out=50, by=7) # use it to generate fridays
by=7 says go to the next Friday.
length.out controls the number of Fridays to generate. One could also use to to control how many Fridays are generated (e.g. use to=as.Date("2013-12-31") instead of length.out).
Takes a year as input and returns only the fridays...
getFridays <- function(year) {
dates <- seq(as.Date(paste0(year,"-01-01")),as.Date(paste0(year,"-12-31")), by = "day")
dates[weekdays(dates) == "Friday"]
}
Example:
> getFridays(2000)
[1] "2000-01-07" "2000-01-14" "2000-01-21" "2000-01-28" "2000-02-04" "2000-02-11" "2000-02-18" "2000-02-25" "2000-03-03" "2000-03-10" "2000-03-17" "2000-03-24" "2000-03-31"
[14] "2000-04-07" "2000-04-14" "2000-04-21" "2000-04-28" "2000-05-05" "2000-05-12" "2000-05-19" "2000-05-26" "2000-06-02" "2000-06-09" "2000-06-16" "2000-06-23" "2000-06-30"
[27] "2000-07-07" "2000-07-14" "2000-07-21" "2000-07-28" "2000-08-04" "2000-08-11" "2000-08-18" "2000-08-25" "2000-09-01" "2000-09-08" "2000-09-15" "2000-09-22" "2000-09-29"
[40] "2000-10-06" "2000-10-13" "2000-10-20" "2000-10-27" "2000-11-03" "2000-11-10" "2000-11-17" "2000-11-24" "2000-12-01" "2000-12-08" "2000-12-15" "2000-12-22" "2000-12-29"
There are probably more elegant ways to do this, but here's one way to generate a vector of Fridays, given any year.
year = 2007
st <- as.POSIXlt(paste0(year, "/1/01"))
en <- as.Date(paste0(year, "/12/31"))
#get to the next Friday
skip_ahead <- 5 - st$wday
if(st$wday == 6) skip_ahead <- 6 #for Saturdays, skip 6 days ahead.
first.friday <- as.Date(st) + skip_ahead
dates <- seq(first.friday, to=en, by ="7 days")
dates
#[1] "2007-01-05" "2007-01-12" "2007-01-19" "2007-01-26"
# [5] "2007-02-02" "2007-02-09" "2007-02-16" "2007-02-23"
# [9] "2007-03-02" "2007-03-09" "2007-03-16" "2007-03-23"
I think this would be the most efficient way and would also returns all the Friday in the whole of 2013.
FirstWeek <- seq(as.Date("2013/1/1"), as.Date("2013/1/7"), "days")
seq(
FirstWeek[weekdays(FirstWeek) == "Friday"],
as.Date("2013/12/31"),
by = "week"
)
I would like to generate a sequence of dates from 10,000 B.C.E. to the present. This is easy for 0 C.E. (or A.D.):
ADtoNow <- seq.Date(from = as.Date("0/1/1"), to = Sys.Date(), by = "day")
But I am stumped as to how to generate dates before 0 AD. Obviously, I could do years before present but it would be nice to be able to graph something as BCE and AD.
To expand on Ricardo's suggestion, here is some testing of how things work. Or don't work for that matter.
I will repeat Joshua's warning taken from ?as.Date for future searchers in big bold letters:
"Note: Years before 1CE (aka 1AD) will probably not be handled correctly."
as.integer(as.Date("0/1/1"))
[1] -719528
as.integer(seq(as.Date("0/1/1"),length=2,by="-10000 years"))
[1] -719528 -4371953
seq(as.Date(-4371953,origin="1970-01-01"),Sys.Date(),by="1000 years")
# nonsense
[1] "0000-01-01" "'000-01-01" "(000-01-01" ")000-01-01" "*000-01-01"
[6] "+000-01-01" ",000-01-01" "-000-01-01" ".000-01-01" "/000-01-01"
[11] "0000-01-01" "1000-01-01" "2000-01-01"
> as.integer(seq(as.Date(-4371953,origin="1970-01-01"),Sys.Date(),by="1000 years"))
# also possibly nonsense
[1] -4371953 -4006710 -3641468 -3276225 -2910983 -2545740 -2180498 -1815255
[9] -1450013 -1084770 -719528 -354285 10957
Though this does seem to work for graphing somewhat:
yrs1000 <- seq(as.Date(-4371953,origin="1970-01-01"),Sys.Date(),by="1000 years")
plot(yrs1000,rep(1,length(yrs1000)),axes=FALSE,ann=FALSE)
box()
axis(2)
axis(1,at=yrs1000,labels=c(paste(seq(10000,1000,by=-1000),"BC",sep=""),"0AD","1000AD","2000AD"))
title(xlab="Year",ylab="Value")
Quite some time has gone by since this question was asked. With that time came a new R package, gregorian which can handle BCE time values in the as_gregorian method.
Here's an example of piecewise constructing a list of dates that range from -10000 BCE to the current year.
library(lubridate)
library(gregorian)
# Container for the dates
dates <- c()
starting_year <- year(now())
# Add the CE dates to the list
for (year in starting_year:0){
date <- sprintf("%s-%s-%s", year, "1", "1")
dates <- c(dates, gregorian::as_gregorian(date))
}
starting_year <- "-10000"
# Add the BCE dates to the list
for (year in starting_year:0){
start_date <- gregorian::as_gregorian("-10000-1-1")
date <- sprintf("%s-%s-%s", year, "1", "1")
dates <- c(dates, gregorian::as_gregorian(date))
}
How you use the list is up to you, just know that the relevant properties of the date objects are year and bce. For example, you can loop over list of dates, parse the year, and determine if it's BCE or not.
> gregorian_date <- gregorian::as_gregorian("-10000-1-1")
> gregorian_date$bce
[1] TRUE
> gregorian_date$year
[1] 10001
Notes on 0AD
The gregorian package assumes that when you mean Year 0, you're really talking about year 1 (shown below). I personally think an exception should be thrown, but that's the mapping users needs to keep in mind.
> gregorian::as_gregorian("0-1-1")
[1] "Monday January 1, 1 CE"
This is also the case with BCE
> gregorian::as_gregorian("-0-1-1")
[1] "Saturday January 1, 1 BCE"
As #JoshuaUlrich commented, the short answer is no.
However, you can splice out the year into a separate column and then convert to integer. Would this work for you?
The package lubridate seems to handle "negative" years ok, although it does create a year 0, which from the above comments seems to be inaccurate. Try:
library(lubridate)
start <- -10000
stop <- 2013
myrange <- NULL
for (x in start:stop) {
myrange <- c(myrange,ymd(paste0(x,'-01-01')))
}