I have a date object as follows:
'2013-01'
'2013-02'
...
How to subtract 1 year from 2013 while keeping the month unchanged, for example
'2012-01'
'2012-02'
...
It can be done by converting to yearmon class and then subtract 1
library(zoo)
format(as.yearmon(str1) - 1, '%Y-%m')
#[1] "2012-01" "2012-02"
Similarly, for subtracting a month, use 1/12
format(as.yearmon(str1) - 1/12, '%Y-%m')
data
str1 <- c('2013-01', '2013-02')
Check with as.POSIXlt
s=as.POSIXlt(paste0(str1,'-01'))
s$year=s$year-1
format(s,'%Y-%m')
[1] "2012-01" "2012-02"
Related
data = data.frame("start"= c("1/2000","8/2004","99/9999"),
"stop"=c("1/2001","2/2007","09/2010"),
"WANTYEARS"= c(1,2.5,NA))
I have date in month/year format and want to subtract to get the years.
My attempt of simple data$stop - data$start did not yield the desired results. THank you.
The yearmon class represents months and years as years and fraction of a year.
Using data shown in the Note at the end:
library(zoo)
transform(data, diff = as.yearmon(stop, "%m/%Y") - as.yearmon(start, "%m/%Y"))
giving:
start stop diff
1 1/2000 1/2001 1.0
2 8/2004 2/2007 2.5
3 99/9999 09/2010 NA
Note
data = data.frame(start= c("1/2000", "8/2004", "99/9999"),
stop = c("1/2001", "2/2007", "09/2010"))
One option is to use difftime from base R. Add "01" to stop and start date to create an actual Date object and subtract those dates using difftime with unit as "weeks" and divide it by number of weeks in year to get time difference in year,
round(difftime(as.Date(paste0("01/", data$stop), "%d/%m/%Y"),
as.Date(paste0("01/", data$start), "%d/%m/%Y"), units = "weeks")/52.2857, 2)
#[1] 1.0 2.5 NA
We can do the same using any other unit component of difftime as well if we know the equivalent year conversion ratio like for example with "days"
round(difftime(as.Date(paste0("01/", data$stop), "%d/%m/%Y"),
as.Date(paste0("01/", data$start), "%d/%m/%Y"), units = "days")/365.25, 2)
#[1] 1.0 2.5 NA
One possibility involving dplyr and lubridate could be:
data %>%
mutate_at(vars(1:2), list(~ parse_date_time(., "my"))) %>%
mutate(WANTYEARS = round(time_length(stop - start, "years"), 1))
start stop WANTYEARS
1 2000-01-01 2001-01-01 1.0
2 2004-08-01 2007-02-01 2.5
3 <NA> 2010-09-01 NA
If I have a given date, how do I find the first and last days of the next month?
For example,
today <- as.Date("2009-04-04")
I want to find
# first date in next month
"2009-05-01"
# last date in next month
"2009-05-31"
You can do this with base R:
today <- as.Date("2009-04-04")
first <- function(x) {
x <- as.POSIXlt(x)
x$mon[] <- x$mon + 1
x$mday[] <- 1
x$isdst[] <- -1L
as.Date(x)
}
first(today)
#[1] "2009-05-01"
first(first(today)) - 1
#[1] "2009-05-31"
lubridate has some useful tools for this purpose.
library(lubridate)
today <- ymd("2009-04-12")
# First day of next month
first <- ceiling_date(today, unit = "month")
# Last day of next month
last <- ceiling_date(first, unit= "month") -1
first
#"2009-05-01"
last
#"2009-05-31"
Here are some solutions. We use today from the question to test. In both cases the input may be a Date class vector.
1) Base R Define function fom to give the first of the month of its Date
argument. Using that we can get the date of the first and last of the next month as follows. We use the facts that 31 and 62 days after the first of the month is necessarily a date in the next month and month after the next month.
fom <- function(x) as.Date(cut(x, "month"))
fom(fom(today) + 31)
## [1] "2009-05-01"
fom(fom(today) + 62) - 1
## [1] "2009-05-31"
2) yearmon yearmon class objects internally represent a year and month as the year plus 0 for January, 1/12 for Febrary, 2/12 for March and so on. Using as.Date.yearmon the frac argument specifies the fraction of the way through the month to output. The default is frac = 0 and results in the first of the month being output and frac = 1 means the end of the month.
library(zoo)
as.Date(as.yearmon(today) + 1/12)
## [1] "2009-05-01"
as.Date(as.yearmon(today) + 1/12, frac = 1)
## [1] "2009-05-31"
I have a data frame in R. It has a column containing dates in this format Dec-06, Jan-90, Feb-76 etc. They are strings. How can I extract year section of it in this format: 2006, 1990, 1976 etc? I want to discard month segment and treat it as distance on year portion of it and treat this column as continuous variable for my logistic regression.
I tried several Date format package provided in R like POSIX, lubridate etc but was not able to extract.
Any idea?
format(as.Date(gsub(".*-","","Dec-06"), format = "%y"), "%Y")
#[1] "2006"
OR
library(lubridate)
format(myd(paste("Dec-06","-01",sep="")), "%Y")
#[1] "2006"
We convert the string into a Date class and then extract only the year from it.
format(as.Date(paste0("01-", x), "%d-%b-%y"), "%Y")
#[1] "2006" "1990" "1976"
data
x <- c("Dec-06", "Jan-90", "Feb-76 ")
Using lubridate , it is easy, year function is a part of lubridate:
library(lubridate)
dat <- data.frame(x=c("Mar-06","Jan-90","May-76"))
dat$date <- as.POSIXlt(paste0("01-",tolower(dat$x)),format="%d-%b-%y",origin="1970-01-01")
dat$year <- year(dat$date)
Answer:
> dat
x date year
1 Mar-06 2006-03-01 2006
2 Jan-90 1990-01-01 1990
3 May-76 1976-05-01 1976
Here is another option with zoo
library(zoo)
data.table::year(as.yearmon("Dec-06", "%b-%y"))
#[1] 2006
Or as #G.Grothendieck mentioned, as.integer returns the year
as.integer(as.yearmon("Dec-06", "%b-%y"))
#[1] 2006
I have a dataframe with a date in the form YYYY-MM, class factor and I am trying to convert it to class date.
I tried:
Date <- c("2015-08","2015-09","2015-08")
Val <- c(1,2,3)
df <- data.frame(Date,Val)
df[,1] <- as.POSIXct(as.character(df[,1]), format = "%Y-%m")
df
But this does not work. I would be grateful for your help.
1) Convert the dates to zoo's "yearmon" class and then to "Date" class:
> library(zoo)
> transform(df, Date = as.Date(as.yearmon(Date)))
Date Val
1 2015-08-01 1
2 2015-09-01 2
3 2015-08-01 3
The question did not specify which date to convert to so we used the first of the month. Had the last of the month been wanted we could have used this instead:
transform(df, Date = as.Date(as.yearmon(Date), frac = 1))
2) Another possibility not using zoo is to just add the day of the month yourself and then convert to "Date" class.
> transform(df, Date = paste(Date, 1, sep = "-"))
Date Val
1 2015-08-01 1
2 2015-09-01 2
3 2015-08-01 3
3) Alternately, might want to just use "yearmon" directly since that directly models year and month with no day.
> library(zoo)
> transform(df, Date = as.yearmon(Date))
Date Val
1 Aug 2015 1
2 Sep 2015 2
3 Aug 2015 3
Note: Do not use "POSIXct" class as this gives a time zone dependent result that can cause subtle errors if you are not careful. A date in one time zone is not necessarily the same as in another time zone.
R does not support Dates in the format "%Y-%m"... A day is needed
You can do the following:
as.POSIXct(paste0(as.character(df[,1]),"-01"), format = "%Y-%m-%d")
Resulting in
"2015-08-01 CEST" "2015-09-01 CEST" "2015-08-01 CEST"
I have dates in an R dataframe column formatted as character strings as WK01Q32014.
I want to turn each date into a Date() object.
So I altered the format to make it look like 01-3-2014. I want to try to do something like as.Date("01-3-2014","%W-%Q-%Y") for example, but there is no format code for quarters that I know of.
Is there any way to do this using the lubridate, zoo, or any other libraries?
I dont know of any specific function, but here's a basic one:
convert_WQ_to_Date <- function(D) {
weeks <- as.integer(substr(D, 3, 4))
quarter <- as.integer(substr(D, 6, 6))
year <- substr(D, 7, 10)
days <- 7 * ((quarter - 1) * 13 + (weeks-1))
as.Date(sprintf("%s-01-01", year)) + days
}
Example
D <- c("WK01Q32014", "WK01Q12014", "WK05Q42014", "WK01Q22014", "WK02Q32014")
convert_WQ_to_Date(D)
[1] "2014-07-02" "2014-01-01" "2014-10-29" "2014-04-02" "2014-07-09"
The week, quarter and year does not uniquely define a date so we will have to add some assumption. Here we add the assumption that the first week is the first day of the quarter, the second week is 7 days later and so on,
Below, we extract the qtr-year part and use as.yearqtr in the zoo package to convert that to a yearqtr object and then use as.Date to convert that to a date which is the first of the quarter. We then extract the week, subtract 1 and multiply by 7 to get the days offset. Adding the first of the quarter to the offset gives the result:
library(zoo)
xx <- "01-3-2014" # week-quarter-year
qtr.start <- as.Date(as.yearqtr(sub("...", "", xx), "%q-%Y"))
days <- 7 * (as.numeric(sub("-.*", "", xx)) - 1)
qtr.start + days
## [1] "2014-07-01"
Assuming the traditional notion of each quarter starting respectively at the 1st January, 1st April, 1st July and 1st September (in line with the quarters function), just start at these dates and add 7 days for each week:
x <- c("01-3-2014","01-1-2014","05-4-2014","01-2-2014","02-3-2014")
y <- as.numeric(substr(x,6,9))
m <- as.numeric(substr(x,4,4))
d <- as.numeric(substr(x,1,2))
as.Date(paste(y,(m-1)*3+1,"01",sep="-")) + (7*(d-1))
#[1] "2014-07-01" "2014-01-01" "2014-10-29" "2014-04-01" "2014-07-08"