2016-04-13 23 views
9

Come posso consentire errori entro \Sexpr?Gestione errori all'interno di Sexpr

Ho un documento knitr. Una piccola parte di questo documento si riferisce a un file che non può essere condiviso. Pertanto, ogni volta che \Sexpr{a} viene richiamato per alcuni oggetti a che dipendono dal file letto, restituisce un errore. Mi piacerebbe invece per \Sexpr stampare che si è verificato un errore.

Ad esempio,

\documentclass{article} 
\usepackage{xcolor} % for red 

\begin{document} 

<<>>= 
x <- 1 
@ 

The value of $x$ is \Sexpr{x} 

<<>>= 
a <- scan("secret_file.txt") 
@ 
The value of $a$ is \Sexpr{a}. 

\end{document} 

non compila (quando secret_file.txt non è presente). Mi piacerebbe che l'output assomigli a qualcosa: Sexpr-error-detected

Ho pensato che modificare l'hook inline avrebbe funzionato, ma mettere il seguente chunk non ha fatto alcuna differenza.

<<Sexpr-setup>>= 
library(knitr) 
knit_hooks$set(inline = function(x){ 
    out <- tryCatch(
    { 
     if (is.numeric(x)) 
     x = round(x, getOption("digits")) 
     paste(as.character(x), collapse = ", ") 
    }, 
    error = function(cond){ 
     return("\\textcolor{red}{\\textbf{Sexpr error!}}") 
     invisible(NULL) 
    }, 
    warning = function(cond){ 
     return("\\textcolor{red}{\\textbf{Sexpr warning!}}") 
     invisible(NULL) 
    } 
) 
    return(out) 
}) 
@ 

Non è essenziale disporre di un messaggio di errore personalizzato, solo che gli errori sono chiari dall'uscita e non impediscono la compilazione. Apprezzo che potrei fare una sostituzione di ritrovamento in qualcosa come \Sexpr{XX( e definire una funzione in primo piano XX() che fa lo stesso tryCatch maneouvre, ma ho pensato knitr could do this.


Calling knitr::knit su quanto sopra e applicando la traceback mostra che:

11: eval(expr, envir, enclos) 
10: eval(parse_only(code[i]), envir = envir) 
9: withVisible(eval(parse_only(code[i]), envir = envir)) 
8: inline_exec(block) 
7: in_dir(opts_knit$get("root.dir") %n% input_dir(), inline_exec(block)) 
6: call_inline(x) 
5: process_group.inline(group) 
4: process_group(group) 
3: withCallingHandlers(if (tangle) process_tangle(group) else process_group(group), 
     error = function(e) { 
      setwd(wd) 
      cat(res, sep = "\n", file = output %n% "") 
      message("Quitting from lines ", paste(current_lines(i), 
       collapse = "-"), " (", knit_concord$get("infile"), 
       ") ") 
     }) 
2: process_file(text, output) 
1: knitr::knit("knitr-prevent-errors.Rnw", quiet = TRUE) 

di dietro alle funzioni, sembra che l'errore è in basso a

eval(parse_only(code[i]), envir = envir) 

Dove code[i] è a. Ho ragione nel pensare che l'unico modo per risolvere questo problema è cambiare la linea che inizia a v = con un tryCatch?

+0

Non sono sicuro se la risposta [qui] (https://stackoverflow.com/questions/ 24978427/suppressing-error-messages-in-knitr) potrebbe essere adattato al tuo problema. La risposta di Josh O'Brien cambia la funzione di errore hook. La documentazione di knitr [qui] (http://yihui.name/knitr/hooks/) suggerisce che questo hook gestisce gli errori sia per i blocchi che per il codice inline. 'error: errori da stop() (si applica agli errori in entrambi i blocchi di codice e nel codice R inline)'.Ho avuto un gioco veloce con l'aggiunta di 'knit_hooks $ set (error = myErrorFunction)' con il tuo codice ma non riuscivo ancora a farlo compilare con '\ Sexpr {a}'. – Graeme

+0

Grazie. Sì, funzionerà solo per le opzioni in-chunk – Hugh

risposta

5

Con l'opzione include=FALSE nel blocco di installazione, il seguente ha funzionato per me con l'output come di seguito. Se non funziona per voi io cancellare il post

enter image description here

\documentclass{article} 
\usepackage{xcolor} % for red 


<<setup, include=FALSE>>= 
knit_hooks$set(inline = function(x) { 

out <- tryCatch(
    { 
     if (is.numeric(x)) 
     x = round(x, getOption("digits")) 
     paste(as.character(x), collapse = ", ") 
    }, 
    error = function(cond){ 
     return("\\textcolor{red}{\\textbf{Sexpr error!}}") 
     invisible(NULL) 
    }, 
    warning = function(cond){ 
     return("\\textcolor{red}{\\textbf{Sexpr warning!}}") 
     invisible(NULL) 
    } 
) 

return(out) 

}) 
@ 



\begin{document} 

<<>>= 
x <- 1 
@ 

The value of $x$ is \Sexpr{x} 

<<>>= 
a <- scan("secret_file.txt") 
@ 
The value of $a$ is \Sexpr{a}. 

\end{document} 

Knitr uscita:

>knitr::knit("test.Rnw") 


processing file: test.Rnw 
    |.........              | 14% 
    ordinary text without R code 

    |...................            | 29% 
label: setup (with options) 
List of 2 
$ include: logi FALSE 
$ indent : chr " " 

    |............................          | 43% 
    ordinary text without R code 

    |.....................................       | 57% 
label: unnamed-chunk-1 (with options) 
List of 1 
$ indent: chr " " 

    |..............................................     | 71% 
    inline R code fragments 

    |........................................................   | 86% 
label: unnamed-chunk-2 (with options) 
List of 1 
$ indent: chr " " 

    |.................................................................| 100% 
    inline R code fragments 


output file: test.tex 

[1] "test.tex" 

Tex Uscita:

>texi2pdf("test.tex") 
> 

Sono utilizzando MikTex 2.9, knitr 1.9, R 3.0.2 su Windows, puoi allegare i tuoi file di registro quindi possiamo confrontare le differenze se esistenti

+0

Quindi non l'ho compilato, ma mi piacerebbe esplorare questo un po 'di più. Cosa ottieni quando "knitr :: knit" è il tuo file? – Hugh

+0

questo non funziona per me – rawr

+0

Come si ottiene questo funziona senza 'library (knitr)' in 'test.Rnw'? – Hugh