I have a data frame containing datetimes (in this case generated with lubridate
, but I don't think that's relevant here) and some dt components extracted. I then want to conditionally alter the datetimes and re-extract those components.
> library(tidyverse)
> library(magrittr)
> library(lubridate)
> df = data_frame(
dt.utc = dts,
date.utc = date(dt.utc),
hour.utc = hour(dt.utc))
# A tibble: 20 x 3
dt.utc date.utc hour.utc
<dttm> <date> <int>
1 2017-01-01 01:00:00 2017-01-01 1
2 2017-01-02 02:00:00 2017-01-02 2
3 2017-01-03 03:00:00 2017-01-03 3
4 2017-01-04 04:00:00 2017-01-04 4
5 2017-01-05 05:00:00 2017-01-05 5
6 2017-01-06 06:00:00 2017-01-06 6
7 2017-01-07 07:00:00 2017-01-07 7
8 2017-01-08 08:00:00 2017-01-08 8
9 2017-01-09 09:00:00 2017-01-09 9
10 2017-01-10 10:00:00 2017-01-10 10
11 2017-01-11 11:00:00 2017-01-11 11
12 2017-01-12 12:00:00 2017-01-12 12
13 2017-01-13 13:00:00 2017-01-13 13
14 2017-01-14 14:00:00 2017-01-14 14
15 2017-01-15 15:00:00 2017-01-15 15
16 2017-01-16 16:00:00 2017-01-16 16
17 2017-01-17 17:00:00 2017-01-17 17
18 2017-01-18 18:00:00 2017-01-18 18
19 2017-01-19 19:00:00 2017-01-19 19
20 2017-01-20 20:00:00 2017-01-20 20
If I use replace()
, I have a problem where the replacement items have to be only as large as the number of replacements (rather than being as large as the original datetimes). So instead I'm using ifelse()
:
> df %<>%
mutate(
dt.new = ifelse(
hour.utc %% 2 == 1 & date.utc > '2017-01-10',
dt.utc + hours(1),
dt.utc))
This correctly combines from dt.utc
and its modified version. But it comes with an unexpected problem: ifelse
appears to be coercing the result to numeric
somewhere along the way:
> df
# A tibble: 20 x 4
dt.utc date.utc hour.utc dt.new
<dttm> <date> <int> <dbl>
1 2017-01-01 01:00:00 2017-01-01 1 1483232400
2 2017-01-02 02:00:00 2017-01-02 2 1483322400
3 2017-01-03 03:00:00 2017-01-03 3 1483412400
4 2017-01-04 04:00:00 2017-01-04 4 1483502400
5 2017-01-05 05:00:00 2017-01-05 5 1483592400
6 2017-01-06 06:00:00 2017-01-06 6 1483682400
7 2017-01-07 07:00:00 2017-01-07 7 1483772400
8 2017-01-08 08:00:00 2017-01-08 8 1483862400
9 2017-01-09 09:00:00 2017-01-09 9 1483952400
10 2017-01-10 10:00:00 2017-01-10 10 1484042400
11 2017-01-11 11:00:00 2017-01-11 11 1484136000
12 2017-01-12 12:00:00 2017-01-12 12 1484222400
13 2017-01-13 13:00:00 2017-01-13 13 1484316000
14 2017-01-14 14:00:00 2017-01-14 14 1484402400
15 2017-01-15 15:00:00 2017-01-15 15 1484496000
16 2017-01-16 16:00:00 2017-01-16 16 1484582400
17 2017-01-17 17:00:00 2017-01-17 17 1484676000
18 2017-01-18 18:00:00 2017-01-18 18 1484762400
19 2017-01-19 19:00:00 2017-01-19 19 1484856000
20 2017-01-20 20:00:00 2017-01-20 20 1484942400
It doesn't appear to be before the combination happens, because wrapping the second and third arguments to ifelse
in ymd_hms
or similar doesn't affect the result.
One clue might be in the ifelse
documentation: 'The mode of the answer will be coerced from logical to accommodate first any values taken from yes and then any values taken from no.'
Does that mean that the test argument (which is boolean
) gets coerced but is ending up numeric
instead of POSIXct
? Do I just need to coerce the result back to POSIXct
myself by wrapping the entire ifelse
function in something?