R time series data, daily only working days - r

I am using the following code:
dates<-seq(as.Date("1991/1/4"),as.Date("2010/3/1"),"days")
However, I would like to only have working days, how can it be done?
(Assuming that 1991/1/4 is a Monday, I would like to exclude: 1991/6/4 and 1991/7/4.
And that for each week.)
Thank you for your help.

Would this work for you? (note, it requires the timeDate package to be installed)
# install.packages('timeDate')
require(timeDate)
# A ’timeDate’ Sequence
tS <- timeSequence(as.Date("1991/1/4"), as.Date("2010/3/1"))
tS
# Subset weekdays
tW <- tS[isWeekday(tS)]; tW
dayOfWeek(tW)

You are entering your dates incorrectly. In order to use the YYYY/DD/MM input mode which is implied by 1991/1/4 being Monday, you need to have a format string in as.Date.
So the full solution assuming you want to exclude weekends is:
X <- seq( as.Date("1991/1/4", format="%Y/%m/%d"), as.Date("2010/3/1", format="%Y/%m/%d"),"days")
weekdays.X <- X[ ! weekdays(X) %in% c("Saturday", "Sunday") ]
# negation easier since only two cases in exclusion
# probably do not want to print that vector to screen.
str(weekdays.X)
Regarding your comment I am unable to reproduce. I get:
> table(weekdays(weekdays.X) )
Friday Monday Thursday Tuesday Wednesday
1000 1000 999 999 999

I came to this question while looking up business day functions, and since the OP requested "business days" instead of "weekdays", and timeDate also has the isBizday function, this answer uses that.
# A timeDate Sequence
date.sequence <- timeSequence(as.Date("1991-12-15"), as.Date("1992-01-15")); # a short example period with three London holidays
date.sequence;
# holidays in the period
years.included <- unique( as.integer( format( x=date.sequence, format="%Y" ) ) );
holidays <- holidayLONDON(years.included) # (locale was not specified by OP in question nor in profile, so this assumes for example: holidayLONDON; also supported by timeDate are: holidayNERC, holidayNYSE, holidayTSX & holidayZURICH)
# Subset business days
business.days <- date.sequence[isBizday(date.sequence, holidays)];
business.days

Related

How can I create a Month-Day vector in R?

I want to create a vector in R, which contains month abbreviation and date:
Jan1, Jan2, Jan3, ..., Dec29, Dec30, Dec31.
How can I create such a vector?
I have tried different approaches. Using paste0(month.abb,1:31) gives me a vector containing Jan1,Feb2,Mar3.
I also created 12 different vectors for each month (df_jan <- paste0("Jan",1:31) and so on). Then I attempted to rbind the 12 vectors, but that also doesn't help.
Can you suggest any way to do this?
The solution is dependent on the year of the dates. A leap year would have Feb29 in it.
Here's a function which takes year as an argument and return dates in the required format.
monthday <- function(year) {
format(seq(as.Date(paste0(year, '-01-01')),
as.Date(paste0(year, '-12-31')), by = 'day'), '%b%d')
}
monthday(2021)
# [1] "Jan01" "Jan02" "Jan03" "Jan04" "Jan05" "Jan06" "Jan07" "Jan08" "Jan09"
#...
#[55] "Feb24" "Feb25" "Feb26" "Feb27" "Feb28" "Mar01" "Mar02" "Mar03" "Mar04"
#....
#[361] "Dec27" "Dec28" "Dec29" "Dec30" "Dec31"
monthday(2020)
# [1] "Jan01" "Jan02" "Jan03" "Jan04" "Jan05" "Jan06" "Jan07" "Jan08" "Jan09"
#....
#[55] "Feb24" "Feb25" "Feb26" "Feb27" "Feb28" "Feb29" "Mar01" "Mar02" "Mar03"
#....
#[361] "Dec26" "Dec27" "Dec28" "Dec29" "Dec30" "Dec31"
You can create a sequence of dates and convert it using format For more details on POSIX standard format use ?strptime
whole_year_dates <- seq.Date(as.Date("2021-01-01"), as.Date("2021-12-31"), by = "day")
whole_year_dates_abbr <- format(whole_year_dates, format= "%b%d")

Getting as.Date to show year only instead of automatically including today's date

When I try to create an XTS object using an existing column with years as characters, my xts object automatically included today's date instead of only the year as I specified it. Is there any way to only include the year?
Here's my code:
global_totals_ts <- xts(global_totals_m[,-1], as.Date(ts_index, format = "%Y"))
and the output that I get is:
Christians Muslims Hindus Agnostics Buddhists
1900-05-17 557754602 200318122 202973290 3028610 126956371
1910-05-17 611362430 222347113 223383337 3368564 138064000
1950-05-17 870653646 338066461 323138775 129261500 175510794
1970-05-17 1229448027 570772699 462980539 544290164 234957917
2000-05-17 1987502477 1292170756 822391937 660693376 452314303
2005-05-17 2130604801 1427056087 893077485 669224713 477436475
I want the following output:
Christians Muslims Hindus Agnostics Buddhists
1900 557754602 200318122 202973290 3028610 126956371
1910 611362430 222347113 223383337 3368564 138064000
1950 870653646 338066461 323138775 129261500 175510794
1970 1229448027 570772699 462980539 544290164 234957917
2000 1987502477 1292170756 822391937 660693376 452314303
2005 2130604801 1427056087 893077485 669224713 477436475
thanks very much!
Date objects will always have days (because dates have days).
One alternative is to keep it as a date, but floor it by year. Then the dates are always the first day of the year, so that, for instance, group_by() operations will be done by year.
library(lubridate)
global_totals_ts <- xts(global_totals_m[,-1], floor_date(as.Date(ts_index, format = "%Y"), "year"))

R: generate dataframe of Friday dates for the year [duplicate]

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"
)

How do I change the index in a csv file to a proper time format?

I have a CSV file of 1000 daily prices
They are of this format:
1 1.6
2 2.5
3 0.2
4 ..
5 ..
6
7 ..
.
.
1700 1.3
The index is from 1:1700
But I need to specify a begin date and end date this way:
Start period is lets say, 25th january 2009
and the last 1700th value corresponds to 14th may 2013
So far Ive gotten this close to this problem:
> dseries <- ts(dseries[,1], start = ??time??, freq = 30)
How do I go about this? thanks
UPDATE:
managed to create a seperate object with dates as suggested in the answers and plotted it, but the y axis is weird, as shown in the screenshot
Something like this?
as.Date("25-01-2009",format="%d-%m-%Y") + (seq(1:1700)-1)
A better way, thanks to #AnandaMahto:
seq(as.Date("2009-01-25"), by="1 day", length.out=1700)
Plotting:
df <- data.frame(
myDate=seq(as.Date("2009-01-25"), by="1 day", length.out=1700),
myPrice=runif(1700)
)
plot(df)
R stores Date-classed objects as the integer offset from "1970-01-01" but the as.Date.numeric function needs an offset ('origin') which can be any staring date:
rDate <- as.Date.numeric(dseries[,1], origin="2009-01-24")
Testing:
> rDate <- as.Date.numeric(1:10, origin="2009-01-24")
> rDate
[1] "2009-01-25" "2009-01-26" "2009-01-27" "2009-01-28" "2009-01-29"
[6] "2009-01-30" "2009-01-31" "2009-02-01" "2009-02-02" "2009-02-03"
You didn't need to add the extension .numeric since R would automticallly seek out that function if you used the generic stem, as.Date, with an integer argument. I just put it in because as.Date.numeric has different arguments than as.Date.character.

Date sequence in R spanning B.C.E. to A.D

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')))
}

Resources