3

Here is my example:

library(dplyr)
my_df <- data.frame(col_1 = c(1,2,4), col_2 = c('2017-12-1', '2015-11-2', '2011-2-5'))
my_df$col_2 <- as.POSIXct(my_df$col_2)
out <- ifelse(my_df$col_1 ==2, my_df$col_2+ as.difftime(3, units = 'days'), NA)
print(out)

It produces:

NA 1446703200         NA

So coercion happens because of different data type. What NA datatype should I use to prevent it: NA_date_ or NA_POSIX_ or ...?

Henrik
  • 65,555
  • 14
  • 143
  • 159
user1700890
  • 7,144
  • 18
  • 87
  • 183

3 Answers3

1

It may be better to do this stepwise with assignment instead of ifelse.

1) Create an index

i1 <- my_df$col_1 == 2

2) Assign values based on the index

my_df$col_2[i1] <- my_df$col_2[i1] + as.difftime(3, units = 'days')

3) Change other elements to NA

my_df$col_2[!i1] <- NA
my_df
#  col_1      col_2
#1     1       <NA>
#2     2 2015-11-05
#3     4       <NA>

The reason is that POSIXct storage mode is numeric, within ifelse it gets coerced to the numeric form


If we are using tidyverse, then

library(tidyverse)
my_df %>%
    mutate(col_2 =  col_2 + days(3), 
           col_2 = replace(col_2, col_1 != 2, NA))
akrun
  • 874,273
  • 37
  • 540
  • 662
1

data.table makes it easy to modify specific rows

require(data.table)
my_df <- data.frame(col_1 = c(1,2,4), col_2 = c('2017-12-1', '2015-11-2', '2011-2-5'))
setDT(my_df)
my_df[, col_2 := as.POSIXct(col_2)
      ][col_1 == 2, col_2 := col_2 + as.difftime(3, units = 'days')
      ][col_1 != 2, col_2 := NA]
IceCreamToucan
  • 28,083
  • 2
  • 22
  • 38
1

Because you (for some reason ;)) have loaded dplyr, you may use if_else and wrap the false NA in as.POSIXct*:

if_else(my_df$col_1 == 2, my_df$col_2 + as.difftime(3, units = 'days'), as.POSIXct(NA))
# [1] NA               "2015-11-05 CET" NA 

*See ?as.POSIXct:

Logical NAs can be converted to either of the classes [POSIXlt and POSIXct]


Related question:

How to prevent ifelse() from turning Date objects into numeric objects. See also the comment by @roarkz and my answer.

Henrik
  • 65,555
  • 14
  • 143
  • 159