Is it possible to use difftime function in R with years ONLY (i.e. no DD/MM)? - r

For example:
Year A
Year B
1990
2021
1980
2021
Thanks in advance.

It depends of what you expect.
If you only want to use the difftime() function with date objects composed only of years (as below), it will work (it will set the day and month to the ones of today for the calculation).
> a = as.Date("2021", format("%Y"))
> b = as.Date("2010", format("%Y"))
> difftime(a,b)
Time difference of 4018 days
But if you want to get the difference in year, it is not possible, as the function documentation clearly state that the return value unit must be: units = c("auto", "secs", "mins", "hours", "days", "weeks")
You might find better way to handle date/time data with the lubridate package.

difftime requests a date object to be used, I tried reproducing this using only years but was unable to.
Why not simply use absolute value (abs())If you're only interested in year difference?
as an example so you can see the difference added to a new column:
Year_A <- c(1990, 1980)
Year_B <- c(2021, 2021)
df <- data.frame(Year_A, Year_B)
df$diff <- abs(Year_A - Year_B)
P.S I noticed the answer above me was added while I was answering and I can't comment to it due to low rep, i see you can't use "years" as a unit value there, the biggest one being weeks, but you can manipulate that from days/weeks to years if that's what you're after.

Related

age_calc in eeptools producing calculation error

I am trying to calculate age in months and one particular date is giving me an incorrect result
See code below. For some reason when the date is March 1, 2019 the age in months is 2.9, which is incorrect, but for March 2, 2019 the function works better although I believe the result should be 4.x.
age_calc(as.Date("10/30/18",format="%m/%d/%y"),as.Date("3/1/19",format="%m/%d/%y"),units="months")
#[1] 2.960829
age_calc(as.Date("10/30/18",format="%m/%d/%y"),as.Date("3/2/19",format="%m/%d/%y"),units="months")
#[1] 3.993088
is this an error in the function? Or I am I doing something wrong? Is this an issue as February has fewer days??
This is perhaps more of an extended comment.
eeptools::age_calc seems to calculate the age in months in an unconventional way (you can see the source code when you type age_calc into an R terminal and hit Enter).
Perhaps a more canonical way to calculate the age between two dates in months is to simply divide the interval by the unit duration. A relevant & interesting post is Get the difference between dates in terms of weeks, months, quarters, and years.
From said post, #Gregor defined a convenient function that does something similar to eeptools::age_calc
library(lubridate)
age <- function(dob, age.day = today(), units = "years", floor = TRUE) {
calc.age = interval(dob, age.day) / duration(num = 1, units = units)
if (floor) return(as.integer(floor(calc.age)))
return(calc.age)
}
Using age we then get
age(
as.Date("10/30/18",format="%m/%d/%y"),
as.Date("3/1/19",format="%m/%d/%y"),
units="months", floor = FALSE)
#[1] 4.010959
age(
as.Date("10/30/18",format="%m/%d/%y"),
as.Date("3/2/19",format="%m/%d/%y"),
units="months", floor = FALSE)
#[1] 4.043836
These values are consistent with values that e.g. Wolfram Alpha gives for the same dates.

Next week day for a given vector of dates

I'm trying to get the next week day for a vector of dates in R. My approach was to create a vector of weekdays and then find the date to the weekend date I have. The problem is that for Saturday and some holidays (which are a lot in my country) i end up getting the previous week day which doesn't work.
This is an example of my problem:
vecDates = as.Date(c("2011-01-11","2011-01-12","2011-01-13","2011-01-14","2011-01-17","2011-01-18",
"2011-01-19","2011-01-20","2011-01-21","2011-01-24"))
testDates = as.Date(c("2011-01-22","2011-01-23"))
findInterval(testDates,vecDates)
for both dates the correct answer should be 10 which is "2011-01-24" but I get 9.
I though of a solution where I remove all the previous dates to the date i'm analyzing, and then use findInterval. It works but it is not vectorized and therefore kind of slow which does not work for my actual purpose.
Does this do what you want?
vecDates = as.Date(c("2011-01-11","2011-01-12",
"2011-01-13","2011-01-14",
"2011-01-17","2011-01-18",
"2011-01-19","2011-01-20",
"2011-01-21","2011-01-24"))
testDates = as.Date(c("2011-01-20","2011-01-22","2011-01-23"))
get_next_biz_day <- function(testdays, bizdays){
o <- findInterval(testdays, bizdays) + 1
bizdays[o]
}
get_next_biz_day(testDates, vecDates)
#[1] "2011-01-21" "2011-01-24" "2011-01-24"

Assigning Day Ranks With Missing Days [duplicate]

I'm looking to find the day of year for a POSIXct class object with lubridate. For example, 12-9-2015 is day 343.
It's easy to find the day of the week or month with lubridate:
> lubridate::wday("2015-12-09 04:27:56 EST", labels = T)
Wed
> lubridate::day("2015-12-09 04:27:56 EST")
9
Is there an easy way to do so for the day of the year? I've searched the documentation and other questions but have not (yet) found an answer.
The correct function is yday, as in
lubridate::yday(Sys.time())
Figured out a more complicated way to do this before stumbling on this answer from u/blindjesse:
# compute the time interval from the first of the year until now
YTD = interval(floor_date(now(), unit='year'), now())
# compute the length of the interval in days, and discard the fractional part
as.integer(time_length(YTD, "day"))
By the way, an even more compact version of u/blindjesse's answer would be:
lubridate::yday(now())

Generate a sequence of time using R and lubridate

Is there an efficient way to generate a time-sequence vector with tidyverse and lubridate? I know the two can work with seq() when one use the number of dates as the interval. For example, with the input:
seq(today(), today()+dyears(1), 60)
one can get a series of dates with a 60-day interval
"2017-02-14" "2017-04-15" "2017-06-14" "2017-08-13" "2017-10-12" "2017-12-11" "2018-02-09"
However, is there any way that this can work for weeks, months and years as well? Perhaps something similar to the code below, which I thought would work but did not:
seq(as_date(2000-01-01), as_date(2017-01-01), dyears(1))
Error: Incompatible duration classes (Duration, numeric). Please coerce with as.duration.
I know it is possible to change dyears(1) into 365 or 30 if one only need an approximation for year or month, but was wondering whether there are smarter ways to take leap years and months into account.
To provide more context, I would like to generate a date vector so I can customize the scale_x_date in ggplot. Instead of letting the waiver() display 2000, 2003, 2006, 2009, I want the plot to have all individual years or even every three-month period if possible.
you could try using seq.Date():
seq.Date(from=as.Date("2000-01-01"), to=as.Date("2010-01-01"), by="month")
or:
seq(as.Date("2000/1/1"), by = "month", length.out = 12)

Creating a specific sequence of date/times in R

I want to create a single column with a sequence of date/time increasing every hour for one year or one month (for example). I was using a code like this to generate this sequence:
start.date<-"2012-01-15"
start.time<-"00:00:00"
interval<-60 # 60 minutes
increment.mins<-interval*60
x<-paste(start.date,start.time)
for(i in 1:365){
print(strptime(x, "%Y-%m-%d %H:%M:%S")+i*increment.mins)
}
However, I am not sure how to specify the range of the sequence of dates and hours. Also, I have been having problems dealing with the first hour "00:00:00"? Not sure what is the best way to specify the length of the date/time sequence for a month, year, etc? Any suggestion will be appreciated.
I would strongly recommend you to use the POSIXct datatype. This way you can use seq without any problems and use those data however you want.
start <- as.POSIXct("2012-01-15")
interval <- 60
end <- start + as.difftime(1, units="days")
seq(from=start, by=interval*60, to=end)
Now you can do whatever you want with your vector of timestamps.
Try this. mondate is very clever about advancing by a month. For example, it will advance the last day of Jan to last day of Feb whereas other date/time classes tend to overshoot into Mar. chron does not use time zones so you can't get the time zone bugs that code as you can using POSIXct. Here x is from the question.
library(chron)
library(mondate)
start.time.num <- as.numeric(as.chron(x))
# +1 means one month. Use +12 if you want one year.
end.time.num <- as.numeric(as.chron(paste(mondate(x)+1, start.time)))
# 1/24 means one hour. Change as needed.
hours <- as.chron(seq(start.time.num, end.time.num, 1/24))

Resources