Subtract months from time in format year-month - r

I want to subtract months from given date in year and month format.
global_date = "2017-01"
I am converting it with the zoo library as follows:
as.yearmon(global_date) - 0.1
but it gives me Nov 2016, I want it as '201612'
How can I do it in R?

As we want to subtract one month, we should subtract 1/12 which is 0.083 and not 0.1
library(zoo)
as.yearmon(global_date) - (1/12)
#[1] "Dec 2016"
If we need output in the mentioned format
format(as.yearmon(global_date) - (1/12), "%Y%m")
#[1] "201612"

Using only base R and making only minimal changes to the OP's code
format(as.Date(paste0(global_date, "-01")) - 0.1*10, "%Y%m")
#[1] "201612"
NOTE: No external packages used

Related

How can as.Date() convert fully written dates into ISO 8601? [duplicate]

This question already has an answer here:
Format for ordinal dates (day of month with suffixes -st, -nd, -rd, -th)
(1 answer)
Closed 1 year ago.
I currently have a vector of dates that are in the following format:
a <- c("Wednesday 26th May 2021","Thursday 27th May 2021")
I've tried to get it into ISO 8601 using the following:
as.Date(a, "%I %d%S %F %Y")
But I'm not 100% certain about the syntax of writing dates.
Any thoughts are appreciated!
You can remove the date suffixes and use as.Date -
#Added an extra date that does not have th as prefix.
a <- c("Wednesday 26th May 2021","Thursday 27th May 2021",
'Tuesday 1st June 2021', 'Monday 31st May 2021')
as.Date(sub('(?<=\\d)(th|rd|st|nd)', '', a, perl = TRUE), '%A %d %b %Y')
#[1] "2021-05-26" "2021-05-27" "2021-06-01" "2021-05-31"
Read ?strptime for different format specification.
If you are open to packages lubridate::dmy works directly.
lubridate::dmy(a)
#[1] "2021-05-26" "2021-05-27" "2021-06-01" "2021-05-31"

in R how to convert a date in character format to numeric and then easily calculate the difference between two dates

So I want to convert "October 2010" and "November 2010" to a numeric format and hence if I take the difference of these two I get result: 1.
I tried to use as.date function but it seems that it only works for full format: month-day-year.
You can try formatting your raw date strings, and treating each one as being on the first day of that month.
dates <- c("October 2010", "November 2010")
# extract the first three letters for the month, and the last 4 digits for the year
dates.new <- paste0(substr(dates, 1, 3), "-01-", substr(dates, nchar(dates)-3, nchar(dates)))
> dates.new
[1] "Oct-01-2010" "Nov-01-2010"
# convert to POSIXct
dates.posix <- as.POSIXct(dates.new, format="%B-%d-%y")
diff <- dates.posix[2] - dates.posix[1]
> diff
Time difference of 31 days
In your question you want to calculate the difference in number of months and not in number of days. You could map your month-year character vector to a numeric number of months, starting at month 1 with the first month in your dataset and ending with month n with the last month in your dataset. Then it would be straightforward to calculate a difference in number of months.
Alternatively - to be able to manipulate date-time objects - you will have to create full dates, by introducing a 01 in front of all dates for example "01 November 2010" and then calculating the difference between dates. This the main part of the answer below.
Manipulating date-time objects
The lubridate package can calculate the difference between two dates. It deals with non trivial issues such as February 29th. If it's not installed on your system:
install.packages("lubridate")
Then
library(lubridate)
ymd("20160301")-ymd("20160228")
# Time difference of 2 days
ymd("20150301")-ymd("20150228")
# Time difference of 1 days
To read full month names look at formatting details in help(parse_date_time)
d <- parse_date_time("November 01 2010", "Bdy") - parse_date_time("October 01 2010", "Bdy")
d
# Time difference of 31 days
d is a difftime object, (based on converting a difftime to integer) you can convert it to a numeric number of days and weeks (but not to a number of months):
class(d)
# [1] "difftime"
as.numeric(d, units="days")
# [1] 31
as.numeric(d, units="weeks")
# [1] 4.428571

Unable to convert Month-Year string to Date in R

I'm using as.Date to convert a string like Aug-2002 to a dates object representing just the month of Aug of 2002, or if a day must be specified, Aug 1, 2002.
However
> as.Date(c('07-2002'), "%M-%Y")
[1] "2002-11-06"
> as.Date(c('Aug-2002'), "%b-%Y")
[1] NA
Why does the first line of code convert it to a different month and day? And the second one is NA?
I referred to this table for the formatting symbols.
The problem you are having is that the dates you have do not have a day value. Without the day value the format="%m-%Y" will not work in as.Date. These options below will solve them:
as.Date(paste0('01-', c('07-2002')), format="%d-%m-%Y")
library(zoo) #this is a little more forgiving:
as.yearmon(c('07-2002'), "%m-%Y")
as.yearmon(c('Aug-2002'), "%b-%Y")
as.Date(as.yearmon(c('07-2002'), "%m-%Y"))

How to convert decimal date format (e.g. 2011.580) to normal date format?

I'm trying to change from the decimal date format (return type of cpts.ts() from the changepoint package) to the normal date format %Y-%m-%d. Example:
cpts.ts(myTimeSeries.BinSeg)
[1] 2001.667 2004.083 2008.750 2011.583 2011.917
The actual dates are sometime around August 2001, January 2004, September 2008, June/July 2011 and December 2011 (I don't know them exactly, I'm reading them off a graph).
I can't seem to find a standard method of converting this format back to the usual date format.
Can anybody help me?
Thanks
Slightly different results with lubridate:
library(lubridate)
decimals <- c(2001.667, 2004.083, 2008.750, 2011.583, 2011.917)
format(date_decimal(decimals), "%Y-%m-%d")
# [1] "2001-09-01" "2004-01-31" "2008-10-01" "2011-08-01" "2011-12-01"
> foo <- c(2001.667,2004.083,2008.750,2011.583,2011.917)
> as.Date(paste(trunc(foo),round((foo-trunc(foo))*365,0)),"%Y %j")
[1] "2001-08-31" "2004-01-30" "2008-09-30" "2011-08-01" "2011-12-01"
Look at ?as.Date and its format parameter, which will direct you to ?strptime, from which I took the %j format specification.
You may need to adapt for some corner cases, like January 1st.
For those considering a base R solution to this issue, the core of lubridate's date_decimal is essentially:
start <- as.POSIXct(paste0(trunc(foo), "/01/01"), tz="UTC")
end <- as.POSIXct(paste0(trunc(foo)+1,"/01/01"), tz="UTC")
start + (difftime(end, start, units="secs") * (foo - trunc(foo)))
I.e. - set a start date back at the start of the year in which the date occurs, set an end date at the start of the following year, multiply the difference between start and end by the fraction of the year elapsed, add this difference back to the start. Doing this takes into account leap years, and will work appropriately for January 1st.

R format of date trouble

I'm confused as to why this as.Date("201410", "%Y%m") is not converted to a date... That is, I expect that the format article of the function as.Date in the example would take the "201410" and convert it to date.
Any help?
If you are willing to make the assumption that these dates are on average occurring at the middle of a month then this would be a dodgy way of using the Date class:
as.Date(paste0("201410", "01"), "%Y%m%d")
#[1] "2014-10-01"
This is how to create a yearmon object:
> require(zoo)
> as.yearmon("201410","%Y%m")
[1] "Oct 2014"

Resources