ruser-defined-functionsdrc

Call a function argument stored in a list


I need to test a suite of argument conditions in order to find the best model (using the drc package). That is, I'd like to store function arguments in a list and then call them into the drm() function. The drc package has a function (mselect()) to do this, but it has been known to fail for unknown reasons (https://www.reddit.com/r/Rlanguage/comments/a1bu44/any_idea_what_im_doing_wrong_with_the_mselect/).


Example Data

library(drc) # This also loads in the S.alba data
data(S.alba)

head(S.alba)
  Dose  Herbicide DryMatter
1    0 Glyphosate       4.7
2    0 Glyphosate       4.6
3    0 Glyphosate       4.1
4    0 Glyphosate       4.4
5    0 Glyphosate       3.2
6    0 Glyphosate       3.0

Failed Attempt

# List of function arguments to be assessed e.g. drm(...fct = W1.4(fixed = c(NA, 0.1, NA, NA)
model_list <- list(curve = c(W1.4(fixed = c(NA, 0.1, NA, NA)),
                             LL.4(fixed = c(NA, 0.1, NA, NA))))

# Failed function, attempting to return a list of results
model_select <- function(data, mlist){
    model =  data %>%
        drm(DryMatter ~ Dose, Herbicide, data = . , fct = mlist)
    metric = AIC(model)
    return(metric)
}
model_select(data = S.alba, mlist = model_list)

Error in drm(DryMatter ~ Dose, Herbicide, data = ., fct = mlist) : First entry in list to 'fct' NOT a function

Semi-Working Attempt

model_select_2 <- function(data){
    model =  data %>%
        drm(DryMatter ~ Dose, Herbicide, data = . , fct = W1.4(fixed = c(NA, 0.1, NA, NA)))
    metric = AIC(model)
    return(metric)
}
model_select_2(data = S.alba)

model_select_2(data = S.alba)
[1] 106.9226

Desired Output

model_select(data = S.alba, mlist = model_list)
[1] W1.4-106.9226
[2] LL.4-99.54702

Solution

  • Part of the problem is how you are creating model_list. You want to combine those values with list() rather than c(). The latter tried to combine them into the same object.

    The next thing you can do is sapply over the list of curves to get the result for each input. A working example would be

    model_list <- list(curve = list(W1.4(fixed = c(NA, 0.1, NA, NA)),
                                 LL.4(fixed = c(NA, 0.1, NA, NA))))
    model_select <- function(data, mlist){
       sapply(mlist$curve, function(curve){
          model <- drm(DryMatter ~ Dose, Herbicide, data = data , fct = curve)
          metric = AIC(model)
       })
    }
    model_select(data = S.alba, mlist = model_list)
    # [1] 106.92259  99.54702