R; lubridate addition of months gives NA [duplicate] - r

This question already has answers here:
Add a month to a Date [duplicate]
(8 answers)
Closed 1 year ago.
I am calculating with dates in a For loop. I combine data from two dataframes. Tibble 1 contains variable A, tibble 2 contains variable B and C.
A is a numerical variable, B and C are both dates.
I want to assign variable A a new variable if date B is within the interval of date C + 16 months.
I used the following:
if (B < C + months(16)) { Df1$A = A+1 }
For some dates this does not work. For example October 30th + 16 months = february 30th. The conditional expression fails as there is no true or falls and the for loop stops.
Is there a way to change C + months(16) to the last day of the month if the specific date (february 30th in the example above) does not exist?

You can use %m+% to add 16 Months.
library(lubridate)
ymd('2000-10-30') %m+% months(16)
#[1] "2002-02-28"

Related

Exclude weekdays while subtracting the dates [duplicate]

This question already has answers here:
Difference between two dates excluding weekends and given list of holidays in R
(2 answers)
Closed 2 years ago.
Is there a way to exclude weekends while taking a difference between dates
as.Date("2021-02-02") - as.Date("2021-01-25")
Time difference of 8 days
Expected output (Since there are 2 days that are weekends and needs to be exlcuded
Time difference of 6 days
Create a sequence between two days, exclude weekends and count the days.
s1 <- as.Date("2021-02-02")
s2 <- as.Date("2021-01-25")
sum(!format(seq(s2, s1, 'day'), '%u') %in% 6:7) - 1
#[1] 6
Does this work, creating a function.
daysdiff <- function(date1, date2){
sum(!weekdays(seq( as.Date(date1), as.Date(date2), 'days')) %in% c('Sunday','Saturday')) - 1
}
daysdiff("2021-01-25", "2021-02-02")
[1] 6

Year column to time series [duplicate]

This question already has answers here:
Convert four digit year values to class Date
(5 answers)
Closed 5 years ago.
OK, this should be really simple but I'm not 'getting it.' I have a data frame with a column "Year" that I want to convert to a time series, but the format is tripping me up. How do I convert the "Year" value to a date, with the actual date being the end of each respective year (e.g. 2015 -> December 31st 2015)?
Year Production
1 1900 38400000
2 1901 43400000
3 1902 49000000
4 1903 44100000
5 1904 49800000
Goal is to get this to a time series data frame. (e.g. xts)
It is not quite the same as a previous question that converted a vector of years to dates. "Convert four digit year values to date type". Goal is to index the data by date, converting it to xts or similar object.
Edited:
This was the final solution:
df <- xts(x = df_original, order.by = as.Date(paste0(df_original[,1], "-12-31")))
whereby the "[,1]" indicates the first column of the original data frame.
If you want each full date to be 31 December, you could use paste along with as.Date to cast to a date:
df$date <- as.Date(paste0(df$Year, "-12-31"))
In addition to Tim Biegeleisen's answer, I will just add another way
df$final_date <- as.Date(ISOdate(df$Year, 12, 31))

Checking if dates are between a range [duplicate]

This question already has answers here:
R - check if string contains dates within specific date range
(2 answers)
Closed 7 years ago.
I have a column with start dates and end dates (plus times).
Then I'd have 31 separate columns, one for each day of the month that contains a 1 or 0 if the start and end dates encompass the day in the column.
I have converted the date values into dates using strptime. I know how to use difftime.
The bit i'm stuck on is actually doing the comparison and checking whether the start date is before or after the date of the column. e.g. i want to know if the start and end date includes the 1st of Jan, then the 2nd of Jan......if the start date is the 5th, i should return 0 for those 2 columns but I don't know how to make the comparison.
Added some sample data
Col 1 Start Date: 01/01/2015 17:00:00
Col 2 End Date: 14/01/2015 10:55:00
Col 3 Jan-01: 1
Col 3 Jan-02: 1
So in columns 3, i'd want to check if start and end date encompasses the 1st of Jan.
The start date can be at some point on the 1st of Jan, e.g. 4pm. If this is the case, i'd like column 3 to return 0.5 days.
Col 1 Start Date: 01/01/2015 00:00:00
Col 2 End Date: 01/01/2015 16:00:00
Col 3 Jan-01: 0.6667
Col 3 Jan-02: 0
Hopefully this is now more clear. I think the complexity of having time and not just returning a Boolean result means this is not a duplicate question.
Since you haven't provided any reproducible date I have created it just to illustrate comparison of two dates and give 1 if TRUE else 0.
Since you mentioned strptimeI am using the same here.
Syntax: ifelse(date1 < date2, 1,0)
> ifelse(strptime(as.Date("2015-12-16"), format = "%Y-%m-%d") < strptime(as.Date("2015-12-17"), format = "%Y-%m-%d"),1,0)
[1] 1
> ifelse(strptime(as.Date("2015-12-18"), format = "%Y-%m-%d") < strptime(as.Date("2015-12-17"), format = "%Y-%m-%d"),1,0)
[1] 0
You can use the same logic to compare two dates.

Using R to count number of specific days in a specific month [duplicate]

This question already has answers here:
Count the number of Fridays or Mondays in Month in R
(3 answers)
Closed 7 years ago.
I'm trying to count the number of Saturdays and then Sundays in a specific month within R.
So for example if you entered the month for example Feb-2014 into the function it would return 4 for Saturday and 4 for Sunday. But if you input Jan-2015 it would return 5 for Saturday and 4 for Sunday.
Any ideas?
You can use lubridate for this. Here's a simple example. You'll have to pass it actual dates (not just months, though):
library("lubridate")
weekend_days <- function(x) {
x <- as.Date(x)
d <- days_in_month(x)
d <- x + (0:(d-1))
sum(wday(d) %in% c(1,7))
}
Some examples (for January and February 2012):
weekend_days("2012-01-01")
# [1] 9
weekend_days("2012-02-01")
# [1] 8

Calculate the week number (0-53) in year

I have a dataset with locations and dates. I would like to calculate week of the year as number (00–53) but using Thursday as the first day of the week. The data looks like this:
location <- c(a,b,a,b,a,b)
date <- c("04-01-2013","26-01-2013","03-02-2013","09-02-2013","20-02-2013","03-03-2013")
mydf <- data.frame(location, date)
mydf
I know that there is strftime function for calculating week of year but it is only possible to use Monday or Sunday as the first day of the week.
Any help would be highly appreciated.
Just add 4 to the Date-formatted values:
> mydf$Dt <- as.Date(mydf$date, format="%d-%m-%Y")
> weeknum <- as.numeric( format(mydf$Dt+3, "%U"))
> weeknum
[1] 1 4 5 6 7 9
This uses a 0 based counting convention since that is what strftime provides and we are just piggybacking off that code base, so the first Friday in a year that begins on Tuesday as was the case in 2013 would be a 1-week result. Add 1 to the value if you want a 1 based convention. (Fundamentally, Date-formated values are in an integer sequence from the "origin" so they don't really recognize years or weeks. Adding 4 just shifts the reference frame of the underlying Date-integer.)
Edit note. Changed to an add three strategy per Gabor's advice. .... which still does not address the question of how to deal with the last week of the prior year.
Since the question stated that week goes from 00-53 we assume that the week number is the number of Thursdays in the year on or before the date in question. Thus, the first Thursday in the year begins week 1 and week 0 is assigned to any days prior to that.
(There were comments that if the first day of the year were Tuesday then that would be week 1 but if that were the case there could never be a week 0 as seems to be required in the subject so some clarification on precisely what the definition of week number is may be required. Here we are going to use the definition in the preceding paragraph but it would not be hard to change it if we knew what the definition was. For example, if we always wanted the first week in the year to be 1 even if it were a short week then we could add !is.thu(jan1(d)) to the result.)
Both of the solutions below are short enough that they could be expressed in one statement; however, we have factored them into several short functions each for clarity. The first is particularly straight forward but the second is automatically vectorized without the need for a sapply and would likely be more efficient.
1. sum Thursdays in year This solution assumes the input d is of class "Date" and just sums the number of Thursdays in the year before or on it:
is.thu <- function(x) weekdays(x) == "Thursday"
jan1 <- function(x) as.Date(cut(x, "year"))
week4 <- function(d) {
sapply(d, function(d) sum(is.thu(seq(jan1(d), d, by = "day"))))
}
We can test it like this:
d <- as.Date(c("2013-01-04", "2013-01-26", "2013-02-03", "2013-02-09",
"2013-02-20", "2013-03-03"))
week4(d) # 1 4 5 6 7 9
2. nextthu
Based on the nextfri function in the zoo quickref vignette we see that the number of days since the Epoch (1970-01-01) of the next Thursday (or the day in question if its already a Thursday) is as given by nextthu in the first line below. Applying this to the first day of the year we derive the result where d is as before:
nextthu <- function(d) 7 * ceiling(as.numeric(d) / 7)
week4a <- function(d) (as.numeric(d) - nextthu(jan1(d))) %/% 7 + 1
and here is a test
week4a(d) # 1 4 5 6 7 9
ADDED: fixed bug in second solution.

Resources