Search code examples
rdplyrtidyverse

Dynamic interaction between mutate and ud.convert leading to miscalculation


I'm working on a dynamic implementation of ud.convert to convert a large dataset with several different units to centimeters, and I ran into an issue. See reproducible example below where everything is converted to inches even when the conversion should be from 'centimeters' to 'cm.'

library(dplyr)
library(udunits2)

fake_data <- tibble::tibble(
     trial_name = c("Trial_A", "Trial_B", "Trial_C", "Trial_D", "Trial_E", "Trial_F"),
     diameter = c(2, 5, 3, 7.5, 10, 4.2),
     diameter_units = c("inches", "centimeters", "inches", "centimeters", "inches", "centimeters")
 )

fake_data %>% 
mutate(datcm = ud.convert(diameter,diameter_units,'cm'))

Output:

  trial_name diameter diameter_units datcm
  <chr>         <dbl> <chr>          <dbl>
1 Trial_A         2   inches          5.08
2 Trial_B         5   centimeters    12.7 
3 Trial_C         3   inches          7.62
4 Trial_D         7.5 centimeters    19.0 
5 Trial_E        10   inches         25.4 
6 Trial_F         4.2 centimeters    10.7 

I can of course fix with explicit ifelse but I wanted this to work more generally. Any ideas on why this is happening would be appreciated!


Solution

  • A comment responding to a similar question points out that ud.convert is not vectorized over the target units argument (u2). You can create a wrapper with Vectorize().

    library(dplyr)
    library(udunits2)
    
    ud.convert.vector <- Vectorize(ud.convert)
    
    fake_data |>
      mutate(datcm = ud.convert.vector(diameter, diameter_units, 'cm'))
    #> # A tibble: 6 × 4
    #>   trial_name diameter diameter_units datcm
    #>   <chr>         <dbl> <chr>          <dbl>
    #> 1 Trial_A         2   inches          5.08
    #> 2 Trial_B         5   centimeters     5   
    #> 3 Trial_C         3   inches          7.62
    #> 4 Trial_D         7.5 centimeters     7.5 
    #> 5 Trial_E        10   inches         25.4 
    #> 6 Trial_F         4.2 centimeters     4.2