0

So I am currently struggling to change the year part of a date using an if function.

My date column looks like this (there are many more values in the real dataframe so it can not be a manual solution):

Date
<S3: POSIXct>
2020-10-31
2020-12-31

I essentially want to create an if command (or any other method) such that if the month is less than 12 (ie. not December) then the year is increased by 1.

So far I have tried using the lubridate package to do:

if (month(df$Date)<12) {
df$Date <- df$Date %m+% years(1)
}

However the function seems to not be conditioning correctly and is instead adding one to every year including those where the month=12

Any help would be greatly appreciated!

Luca
  • 57
  • 1
  • 5
  • `if` requires its conditional to be precisely length 1 (not 0, not 2 or more), so if your `df` has other than 1 row, that should be providing a clear warning that you should *not* be doing that. One might think to try `ifelse`, but that is [ill-advised](https://stackoverflow.com/q/6668963/3358272). One might try `replace` instead, it doesn't share the same fate as `ifelse`. – r2evans Feb 25 '21 at 20:25
  • Thank you that got me onto the right track and started looking at another approach which I have posted below – Luca Feb 25 '21 at 20:40

2 Answers2

1

You could approach it like this:

library(lubridate)

dates <- seq.Date(from = as.Date('2015-01-01'),
                  to = Sys.Date(),
                  by = 'months')
indicator <- month(dates) < 12

dates2 <- dates
dates2[indicator] <- dates[indicator] %m+% years(1)

res <- data.frame(dates, indicator, dates2)
> head(res, 25)
        dates indicator     dates2
1  2015-01-01      TRUE 2016-01-01
2  2015-02-01      TRUE 2016-02-01
3  2015-03-01      TRUE 2016-03-01
4  2015-04-01      TRUE 2016-04-01
5  2015-05-01      TRUE 2016-05-01
6  2015-06-01      TRUE 2016-06-01
7  2015-07-01      TRUE 2016-07-01
8  2015-08-01      TRUE 2016-08-01
9  2015-09-01      TRUE 2016-09-01
10 2015-10-01      TRUE 2016-10-01
11 2015-11-01      TRUE 2016-11-01
12 2015-12-01     FALSE 2015-12-01
13 2016-01-01      TRUE 2017-01-01
14 2016-02-01      TRUE 2017-02-01
15 2016-03-01      TRUE 2017-03-01
16 2016-04-01      TRUE 2017-04-01
17 2016-05-01      TRUE 2017-05-01
18 2016-06-01      TRUE 2017-06-01
19 2016-07-01      TRUE 2017-07-01
20 2016-08-01      TRUE 2017-08-01
21 2016-09-01      TRUE 2017-09-01
22 2016-10-01      TRUE 2017-10-01
23 2016-11-01      TRUE 2017-11-01
24 2016-12-01     FALSE 2016-12-01
25 2017-01-01      TRUE 2018-01-01
tester
  • 1,662
  • 1
  • 10
  • 16
  • Many thanks for the solution! I managed to find my own in that time which I have posted below! – Luca Feb 25 '21 at 20:42
0

Found a more direct solution which doesnt use if commands.

df$Date[month(df$Date)<12] <- df$Date[month(df$Date)<12] %m+% years(1)

This still uses the month function in the lubridate package to get the conditions

Luca
  • 57
  • 1
  • 5
  • This is almost exactly what @tester proposed, albeit not using the intermediate `indicator` variable. (I suggest you accept that answer, though keeping this answer here is fine.) – r2evans Feb 25 '21 at 20:59
  • Why is tester's answer more right? The indicator variable does not add any benefit – CALUM Polwart Feb 25 '21 at 21:42