1
library(nlme)
fm1 <- nlme(height ~ SSasymp(age, Asym, R0, lrc),
              data = Loblolly,
              fixed = Asym + R0 + lrc ~ 1,
              random = Asym ~ 1,
              start = c(Asym = 103, R0 = -8.5, lrc = -3.3), verbose = TRUE)

# **Iteration 1
# LME step: Loglik: -114.787, nlminb iterations: 1
# reStruct  parameters:
#      Seed 
# -1.669062 
# PNLS step: RSS =  43.40812 
#  fixed effects: 101.4496  -8.627331  -3.233751  
#  iterations: 4 
# Convergence crit. (must all become <= tolerance = 1e-05):
#      fixed   reStruct 
# 0.02048682 0.02712258 
# 
# **Iteration 2
# LME step: Loglik: -114.7428, nlminb iterations: 1
# reStruct  parameters:
#      Seed 
# -1.624988 
# PNLS step: RSS =  43.40812 
#  fixed effects: 101.4496  -8.627331  -3.233751  
#  iterations: 1 
# Convergence crit. (must all become <= tolerance = 1e-05):
#    fixed reStruct 
#        0        0 

In particular, I am referring to the nlme function call, but I think the solution will be generalizable to other verbose = TRUE generated outputs. Essentially, I would like to store the verbose text (starting from **Iteration 1). Is there any way to do this in R?

Edit: Gregor de Cilla's answer works great for the above example (where algorithm converged). What if the algorithm didn't converge?

u2 = evaluate({
fm2 <- nlme(height ~ SSasymp(age, Asym, R0, lrc),
            data = Loblolly,
            fixed = Asym + R0 + lrc ~ 1,
            random = Asym ~ 1,
            start = c(Asym = 103, R0 = -10, lrc = -8), verbose = TRUE)
})
> cat(u2[[2]])
# Error in cat(u2[[2]]) : object 'u2' not found
Adrian
  • 9,229
  • 24
  • 74
  • 132

2 Answers2

1

The evaluate package is handy for such tasks. Here is an Example

library(evaluate)
library(nlme)

u = evaluate({
  fm1 <- nlme(height ~ SSasymp(age, Asym, R0, lrc),
              data = Loblolly,
              fixed = Asym + R0 + lrc ~ 1,
              random = Asym ~ 1,
              start = c(Asym = 103, R0 = -8.5, lrc = -3.3), verbose = TRUE)
})

# get the output in character form
output_str = u[[2]]

# check if everything worked
cat(output_str)

If you want better control over which kind of outputs are saved, take a look at the evaluate::new_output_handler documentation.

In case of errors, wrapping your expression inside a function is advisable

u2 = evaluate({
  function(){
    fm2 <- nlme(height ~ SSasymp(age, Asym, R0, lrc), data = Loblolly, 
                fixed = Asym + R0 + lrc ~ 1, 
                random = Asym ~ 1, 
                start = c(Asym = 103, R0 = -10, lrc = -8), 
                verbose = TRUE)
  }
})

The error messages can then be captured from u2[[3]].

EDIT: Since you asked, running this will show how the new_output_handler function works

my_output_handler = new_output_handler(
  error = function(x) {
    cat("source_prefix:", as.character(x))
  }
)

u2 = evaluate({
  function(){
    fm2 <- nlme(height ~ SSasymp(age, Asym, R0, lrc), data = Loblolly, 
                fixed = Asym + R0 + lrc ~ 1, 
                random = Asym ~ 1, 
                start = c(Asym = 103, R0 = -10, lrc = -8), 
                verbose = TRUE)
  }
}, output_handler = my_output_handler)

replay(u2)
Gregor de Cillia
  • 7,397
  • 1
  • 26
  • 43
  • Thanks. Is there also a way to do this for models that have errors? I edited my main post. – Adrian Jun 27 '17 at 13:24
  • I already pointed you to the `new_output_hanler` documentation. There you can define callbacks for error messages. – Gregor de Cillia Jun 27 '17 at 13:30
  • Yes, I understand. There seems to be no example code in the documentation, so I am a bit lost. I've been trying `u2 = evaluate({ fm2 <- nlme(height ~ SSasymp(age, Asym, R0, lrc), data = Loblolly, fixed = Asym + R0 + lrc ~ 1, random = Asym ~ 1, start = c(Asym = 103, R0 = -10, lrc = -8), verbose = TRUE) }, message = identity, error = identity, warning = identity)` but that didn't seem to work. – Adrian Jun 27 '17 at 13:34
  • I just found out that quoting your expression will work. I.e. `evaluate({"fmi1<-..."})` – Gregor de Cillia Jun 27 '17 at 13:46
0

To send output back to the console: sink() for output and sink(type = "message") for stderr. See examples in ? sink.

see How to capture RCurl verbose output

Ajay Ohri
  • 3,382
  • 3
  • 30
  • 60