Search code examples
rclassdplyrlubridateacross

How to differentiate between interval and numeric columns in dplyr::across()?


I have a tibble containing Intervals, created with lubridate.

library(tidyverse)
Interval=lubridate::interval(POSIXct(1)+1,POSIXct(1))
numeric=3
character="A"
tbl<-tibble(Interval,numeric,character)

with the title reflecting the class of the data in each column. I want to apply a function to the numeric column only. Unfortunately, Interval is of type double: ''' typeof(Interval) [1] "double" ''' So that mutate(tbl,across(is.double,mean)) renders

# A tibble: 1 × 3
  Interval numeric character
     <dbl>   <dbl> <chr>    
1       -1       3 A       

I do get the desired result with: mutate(tbl,across(is.numeric&!is.interval,mean))

 Interval                                numeric character
 <Interval>                                <dbl> <chr>    
1 1970-01-01 00:00:01 UTC--1970-01-01 UTC       3 A    

But this seems quite tiresome. Is there a more direct way to just select for numeric, excluding Interval?


Solution

  • Use rlang::is_bare_double().

    library(dplyr)
    library(rlang)
    
    mutate(tbl, across(where(is_bare_double), mean))
    
    # A tibble: 1 × 3
      Interval                                numeric character
      <Interval>                                <dbl> <chr>    
    1 1970-01-01 00:00:01 UTC--1970-01-01 UTC       3 A        
    

    Also note the predicate should be wrapped in where(); it will still work unwrapped, but yields a warning since this is deprecated.