2017-10-17 6 views
0

J'essaye d'accélérer mon code en remplaçant les boucles par lapply. J'exécute des modèles nls sur beaucoup d'échantillons différents et en extrayant les coefficients, mais certains modèles ne convergent pas pour certains échantillons. Je pourrais gérer cela avec une boucle for avec trycatch pour ignorer ces échantillons, mais je ne peux pas le faire fonctionner avec lapply. Quand je lance ceci, j'obtiens une liste de mes samples.code et NULL, où devrais-je placer le return (nls.dat)? partie donc je ne finis pas juste le NULL?Sortie NULL de lapply et trycatch

test.func <- function (SCDF){ 
    tryCatch({ 
    mod.allDIDO <- nlsLM (BM~Cr*(1 - R * exp(-Kr*day) - (1 - R) * exp(-Kr2*day)), data=dat[dat$sample.code %in% SC,], start=list(Cr=DI.Cr,R=DI.r,Kr=DI.Kr,Kr2=DI.Kr2), 
         control = nls.lm.control(maxiter = 500), lower = c(-Inf, 0, 0, 0), upper = c(Inf, 1, Inf, Inf)) 
    nls.dat <- c("df", coef(mod.allDIDO)[1], coef(mod.allDIDO)[2], coef(mod.allDIDO)[3], coef(mod.allDIDO)[4], deviance(mod.allDIDO), logLik(mod.allDIDO)) 
    return (nls.dat) 
    }, error = function(e){}) 
} 

test1 <- lapply(split(dat, dat$sample.code), test.func) 

modifié pour inclure des données et répondre à Carl: J'ai essayé votre suggestion (Carl) mais je reçois toujours NULL, voir réduire la version

x1 <- 0:60 
y1 <- 774*(1 - 0.5 * exp(-0.2*x1) - (1 - 0.5) * exp(-0.016*x1)) 
test.dat <- data.frame (x1, y1) 

    nls.dat <- tryCatch({ 
    mod.allDIDO <- nlsLM(y1~Cr*(1 - R * exp(-Kr*x1) - (1 - R) * exp(-Kr2*x1)), 
         data=test.dat, 
         start=list(Cr=774,R=0.5,Kr=0.2,Kr2=0.016), 
         control = nls.lm.control(maxiter = 500), 
         lower = c(-Inf, 0, 0, 0), 
         upper = c(Inf, 1, Inf, Inf)) 
    nls.dat <- c("df", coef(mod.allDIDO)[1], 
       coef(mod.allDIDO)[2], 
       coef(mod.allDIDO)[3], 
       coef(mod.allDIDO)[4], 
       deviance(mod.allDIDO), 
       logLik(mod.allDIDO)) 
    return(nls.dat) 
    }, error = function(e){}) 

    nls.dat ## NULL 

Répondre

0

La chose à faire attention à est votre environnements d'appel. Les parenthèses tryCatch traitent les appels contenus comme leurs propres fonctions. Vous avez donc besoin de retourner le retuirn du tryCatch à l'environnement parent, puis revenir de la fonction, comme ceci:

test.func <- function (SCDF){ 
    nls.dat <- tryCatch({ 
    mod.allDIDO <- nlsLM(BM~Cr*(1 - R * exp(-Kr*day) - (1 - R) * exp(-Kr2*day)), 
         data=dat[dat$sample.code %in% SC,], 
         start=list(Cr=DI.Cr,R=DI.r,Kr=DI.Kr,Kr2=DI.Kr2), 
         control = nls.lm.control(maxiter = 500), 
         lower = c(-Inf, 0, 0, 0), 
         upper = c(Inf, 1, Inf, Inf)) 

    nls.dat <- c("df", coef(mod.allDIDO)[1], 
       coef(mod.allDIDO)[2], 
       coef(mod.allDIDO)[3], 
       coef(mod.allDIDO)[4], 
       deviance(mod.allDIDO), 
       logLik(mod.allDIDO)) 
    return(nls.dat) 
    }, error = function(e){ 
    NULL 
    }) 
    return(nls.dat) 
} 

Modifier

C'est un comportement étrange ... donc je l'ai testé une autre façon que je le ferais Ne jamais faire ... mais pour une raison quelconque cela fonctionne ... Nouvelle fonction prend la variable et ajoute une instruction if pour ajouter un autre ... vérification logique apparemment inutile .. mais cela fonctionne. Vérifie si la valeur est NULL, sinon les rendements, et s'il y a une erreur partout dans les deux étapes ... il par défaut à la error = function(e) {NULL}

f <- function(x1, y1, test.dat){ 
    tryCatch({ 
     mod.allDIDO <- nlsLM(y1~Cr*(1 - R * exp(-Kr*x1) - (1 - R) * exp(-Kr2*x1)), 
         data=test.dat, 
         start=list(Cr=774,R=0.5,Kr=0.2,Kr2=0.016), 
         control = nls.lm.control(maxiter = 500), 
         lower = c(-Inf, 0, 0, 0), 
         upper = c(Inf, 1, Inf, Inf)) 
    nls.dat <- c("df", coef(mod.allDIDO)[1], 
       coef(mod.allDIDO)[2], 
       coef(mod.allDIDO)[3], 
       coef(mod.allDIDO)[4], 
       deviance(mod.allDIDO), 
       logLik(mod.allDIDO)) 
    if(!is.null(nls.dat)){ 
     return(nls.dat) 
    }else { 
     NULL 
    } 
}, error = function(e){NULL}) 
} 

et en cours d'exécution ...

> f(x1 = x1, y1 = y1, test.dat = test.dat) 
      Cr  R  Kr  Kr2     
    "df" "774" "0.5" "0.2" "0.016"  "0" "Inf" 
+0

Salut Carl, j'ai essayé votre suggestion mais la sortie était toujours NULL, voir la version réduite et quelques données dans la question éditée. – chris20

+0

ci-dessus œuvres post-édition ... merci pour les données. Utile aussi si vous incluez des paquets que vous utilisez ..déchaînez 'minpack.lm'. Aucune idée pourquoi la double-prise logique est utile ... mais cela fonctionne. –

+0

Merci Carl, cela fonctionne très bien, désolé j'ai oublié d'ajouter le paquet. – chris20