rfor-looptestinglubridate

Creating test for date columns incorrectly throwing error


I want to run a test to verify that all date columns in a df are in the 'ymd' order.

I'm using the code below (data given at the end)

date_stop = function(df_date, date_order){
  
  #get only date columns
  dates_only <- unlist(lapply(df_date, lubridate::is.Date), use.names = FALSE) 
  
  date_cols = df_date[, dates_only]
  
  #check all date columns for correct date order

  stopifnot(
    for (date_col in date_cols){
      !is.na(lubridate::parse_date_time(date_col, orders= date_order)
     )
      }, return(date_cols)
  )
}

date_stop(df, 'ymd')

However, this is throwing a false error Error in date_stop(ccbh, "ymd") : for (date_col in date_cols) { .... are not all TRUE, because if I run these columns individually, they all have the correct format. Is there something I'm missing?

I also noticed something weird with stopifnot in that I can't pipe into it; for instance, with the data below, this does not work date_cols%>%stopifnot(Date_opened == Date_opened) but this does stopifnot(date_cols$Date_opened == date_cols$Date_opened) Why is that?

df = structure(list(Dob = structure(c(13004, 12040), class = "Date"), 
    Date_opened = structure(c(19465, 19299), class = "Date"), 
    Date_closed = structure(c(19541, 19710), class = "Date"), 
    Date_closed_original = structure(c(19541, 19710), class = "Date"), 
    Date_closed_fy = structure(c(19541, 19710), class = "Date"), 
    other = c(14, 15)), class = "data.frame", row.names = c(NA, 
-2L))

Solution

  • I agree with the comments that there is no need to test the format of a numeric date, it is always YYYY-MM-DD. To answer the question about the stopifnot(), you have stopifnot() testing the value returned by the for loop, which returns NULL. If you move the stopifnot() inside the loop to test each column, the loop will complete with your example data.

    for (date_col in date_cols){
      stopifnot(!is.na(lubridate::parse_date_time(date_col, orders= date_order)
      ))
    }