Search code examples
rerror-handlingdata.tabletry-catchnls

Skipping errors in data table computation using nls


This question builds off a previous one I asked here Exponential curve fitting with nls using data.table groups.

I am fitting exponential curves using nls to a data table object by multiple groups. Not all of the data appears to fit an exponential model and nls sometimes throws an error, stopping all further calculations for the remaining groups.

I've attached a MWE below with my attempt at using a tryCatch to skip problematic groups but I end up with the error output for all of my new columns. How can I skip calculating nls values for my problematic groups?

## Example data table
DT <- data.table(
     x = c(1,2,3,4,5,6,7,8,
           1,2,3,4,5,6,7,8,
           1,2,3,4,5,6,7,8),
     y = c(15.4,16,16.4,17.7,20,23,27,35,
           25.4,26,26.4,27.7,30,33,37,45,
           27.4,28,28.4,29.7,32,35,39,47),
groups = c(1,1,1,1,1,1,1,1,
           2,2,2,2,2,2,2,2,
           3,3,3,3,3,3,3,3)
)

## Fit exponential curve using starting values a,b,c for each group 
DT[, c("sigma", "a", "b", "c") := {
    c.0 <- min(y) * 0.5
    model.0 <- lm(log(y - c.0) ~ x, data=.SD)
    start <- list(a=exp(coef(model.0)[1]), b=coef(model.0)[2], c=c.0)
    model <- nls(y ~ a * exp(b * x) + c,
        data=.SD, 
        start=start, 
        control=nls.control(maxiter=500))
    c(.(sigma=summary(model)$sigma), as.list(coef(model)))
},
by=.(groups)]

## Modify data table to ruin nls model for group 2
set(DT, i=16L, j="y", value=3)

## Calculation works for group 1 but stops for group 2 and onwards
DT[, c("sigma", "a", "b", "c") := {
    c.0 <- min(y) * 0.5
    model.0 <- lm(log(y - c.0) ~ x, data=.SD)
    start <- list(a=exp(coef(model.0)[1]), b=coef(model.0)[2], c=c.0)
    model <- nls(y ~ a * exp(b * x) + c,
        data=.SD, 
        start=start, 
        control=nls.control(maxiter=500))
    c(.(sigma=summary(model)$sigma), as.list(coef(model)))
},
by=.(groups)]

## My poor attempt at using a tryCatch just gives NA to every column
DT[, c("sigma","a", "b", "c") := {
    c.0 <- min(y) * 0.5
    model.0 <- lm(log(y - c.0) ~ x, data=.SD)
    start <- list(a=exp(coef(model.0)[1]), b=coef(model.0)[2], c=c.0)
    model <- tryCatch(
        {
            nls(y ~ a * exp(b * x) + c,
                data=.SD, 
                start=start, 
                control=nls.control(maxiter=500))
            c(.(sigma=summary(model)$sigma), as.list(coef(model)))
        },
        error=function(err){
            return(NA_real_)
        }
    )
},
by=.(groups)]

Solution

  • No need to mark, too long in a comment.

    Something like this:

    DT[, c("sigma", "a", "b", "c") := 
        tryCatch({
            c.0 <- min(y) * 0.5
            model.0 <- lm(log(y - c.0) ~ x, data=.SD)
            start <- list(a=exp(coef(model.0)[1]), b=coef(model.0)[2], c=c.0)
            model <- nls(y ~ a * exp(b * x) + c,
                data=.SD,
                start=start,
                control=nls.control(maxiter=500))
            c(.(sigma=summary(model)$sigma), as.list(coef(model)))
        }, error=function(e) NA_real_),
        by=.(groups)]
    

    output:

        x    y groups     sigma         a         b        c
     1: 1 15.4      1 0.2986243 0.5265405 0.4565363 14.56728
     2: 2 16.0      1 0.2986243 0.5265405 0.4565363 14.56728
     3: 3 16.4      1 0.2986243 0.5265405 0.4565363 14.56728
     4: 4 17.7      1 0.2986243 0.5265405 0.4565363 14.56728
     5: 5 20.0      1 0.2986243 0.5265405 0.4565363 14.56728
     6: 6 23.0      1 0.2986243 0.5265405 0.4565363 14.56728
     7: 7 27.0      1 0.2986243 0.5265405 0.4565363 14.56728
     8: 8 35.0      1 0.2986243 0.5265405 0.4565363 14.56728
     9: 1 25.4      2        NA        NA        NA       NA
    10: 2 26.0      2        NA        NA        NA       NA
    11: 3 26.4      2        NA        NA        NA       NA
    12: 4 27.7      2        NA        NA        NA       NA
    13: 5 30.0      2        NA        NA        NA       NA
    14: 6 33.0      2        NA        NA        NA       NA
    15: 7 37.0      2        NA        NA        NA       NA
    16: 8  3.0      2        NA        NA        NA       NA
    17: 1 27.4      3 0.2986243 0.5265401 0.4565364 26.56728
    18: 2 28.0      3 0.2986243 0.5265401 0.4565364 26.56728
    19: 3 28.4      3 0.2986243 0.5265401 0.4565364 26.56728
    20: 4 29.7      3 0.2986243 0.5265401 0.4565364 26.56728
    21: 5 32.0      3 0.2986243 0.5265401 0.4565364 26.56728
    22: 6 35.0      3 0.2986243 0.5265401 0.4565364 26.56728
    23: 7 39.0      3 0.2986243 0.5265401 0.4565364 26.56728
    24: 8 47.0      3 0.2986243 0.5265401 0.4565364 26.56728
        x    y groups     sigma         a         b        c