Search code examples
rrlangtidyeval

Checking the class of a column in a function that uses tidy evaluation


I am not referring to the column name as a string, but how can I check the class in the if statement when I am not referring to the column name as a string:

My problem is with the if statement bellow: I have tried rlang::as_name, quote etc.

df <- tibble::tibble( time_text = as.character(as.POSIXct("2018-02-03 08:00:00", tz = "UTC") + rnorm(100, 0, 60*60*60)))

date_from_text <- function(df, x){

  if(!class(df[[deparse(x)]]) %in% c("POSIXct", "POSIXt" )) {

  x <- rlang::enquo(x)
  name <- rlang::quo_name(x)

 out <-  df %>%
    dplyr::mutate(!!name := lubridate::ymd_hms(!!x))
  }
  else {
    stop("Seems that column is in the right format already")
       }  
}

date_from_text(df, time_text)
 Error in deparse(x) : object 'time_text' not found 

Solution

  • It works when you use the x <- rlang::enquo(x) and name <- rlang::quo_name(x) before the if-statement:

    date_from_text <- function(df, x){
    
      x <- rlang::enquo(x)
      name <- rlang::quo_name(x)
    
      if(!inherits(df[[name]], c("POSIXct", "POSIXt"))) {
    
        out <- dplyr::mutate(df, !!name := lubridate::ymd_hms(!!x))
    
      } else {
    
        stop("Seems that column is in the right format already")
    
      }  
    }
    

    I changed the requirement in the if-statement to !inherits(df[[name]], c("POSIXct", "POSIXt")).
    In your original code only the first element of the class vector would be checked, whereas inherits checks if any of the specified classes is inherited.

    my.df <- tibble::tibble(time_text = as.character(as.POSIXct("2018-02-03 08:00:00", tz = "UTC") + rnorm(100, 0, 60*60*60)))
    
    my.df2 <- date_from_text(my.df, time_text)
    my.df2
    # A tibble: 100 x 1
    #   time_text          
    #   <dttm>             
    # 1 2018-02-06 18:38:46
    # 2 2018-01-31 16:16:15
    # 3 2018-02-04 05:52:32
    # 4 2018-02-05 23:31:50
    # 5 2018-02-06 13:00:34
    # 6 2018-02-01 16:16:24
    # 7 2018-02-05 15:09:45
    # 8 2018-02-04 04:23:00
    # 9 2018-02-03 06:55:18
    # 10 2018-01-29 01:06:26
    # ... with 90 more rows
    
    date_from_text(my.df2, time_text)
    

    Error in date_from_text(my.df2, time_text) : Seems that column is in the right format already

    Thanks to @KonradRudolph for improving this answer with his comments.