rfunctiondplyrfiltermasking

Masking issue when applying a function on a tibble


I have a simple function that takes two key parameters and returns a corresponding value from a tibble. The function works totally fine when I pass single values as arguments. But when applied to a tibble, the error wsa_m2 must be size 3 or 1, not 0 comes up.

require("tidyverse")

wsa <- tibble("trim" = c(4, 4, 4, 5, 5, 5, 6, 6, 6), 
               "draught" = c(7, 8, 9, 7, 8, 9, 7, 8, 9), 
               "wsa" = c(100, 200, 300, 400, 500, 600, 700, 800, 900))

data <- tibble("draught_m" = c(6, 5, 4), "trim_m" = c(9, 8, 7))

get_wsa <- function(draught_m, trim_m, wsa_tab) {
  filter(wsa_tab, draught == draught_m & 
           trim == trim_m)$wsa
}

# works perfectly fine
a <- get_wsa(draught_m = 7, trim_m = 5, wsa_tab = wsa)

# error
data2 <- mutate(data, wsa_m2 = get_wsa(draught_m = data$draught_m, 
                                       trim_m = data$trim_m, 
                                       wsa_tab = wsa))

The Backtrace indicates that this seems to be a masking issue. I already tried solving the issue using enquo(), but didn't succeed... Any help is much appreciated!

Thanks in advance, Jonas


Solution

  • First of all, I think you have your columns interchanged in one of the dataframe. I am correcting data dataframe.

    data <- tibble("trim_m" = c(6, 5, 4), "draught_m" = c(9, 8, 7))
    

    But even after that it will not give the correct answer because when you run example by "hand" you only pass a single value but data$draught_m and data$trim_m have 3 values in. them. So you need to add rowwise to your code so that it executes for each row individually.

    data2 <- data %>%
      rowwise() %>%
      mutate(wsa_m2 = get_wsa(draught_m = draught_m, trim_m, wsa_tab = wsa))
    
    data2
    # A tibble: 3 × 3
    # Rowwise: 
    #  trim_m draught_m wsa_m2
    #   <dbl>     <dbl>  <dbl>
    #1      6         9    900
    #2      5         8    500
    #3      4         7    100
    

    However, that can be inefficient for larger database and you should try using join instead.

    data %>%
      left_join(wsa, join_by(trim_m == trim, draught_m == draught))