Sweave + RweaveHTML: cat output does not appear in the output - r

I have a problem with Sweave + RweaveHTML
I want the output of cat ends to up in the html file being generated. I have a case in which it does not and I can't figure out why :(
test = function()
{
#bla bla;
cat("Result is...")
}
And then in the Rnw file I tried all of these:
<<echo=FALSE, results=html, include=TRUE>>=
test()
#
<<results=html, include=TRUE>>=
test()
#
<<results=html>>=
test()
#
<<>>=
test()
#
But I don't get the cat output in the resulting HTML file.
I'm pretty sure this is supposed to work...
Any ideas of what I'm supposed to do to get the stdout ouput to the final html file?
Thx!

The RweaveHTML driver works differently than the RweaveLatex driver in that to create output, the result from every line of code is processed with the generic function HTML. Other ways of creating output don't work. So to get output from within a function, there are two ways I know of; one is to return a value to be processed by the HTML generic, and the other is to call HTML directly. The following replacement of your test function demonstrates both.
test <- function() {
#bla bla;
HTML("Result is...")
"Return value is"
}
It's also possible to replace cat with HTML; then your original function would work. But it's a bit of a hack and could have unforeseen consequences; you'd put
cat <- HTML
in a (probably hidden) Sweave chunk at the beginning of the document.

Related

Printing from a function in Rmarkdown that allows newlines and escaping Markdown and Latex commands

I am trying to write a function for use in Rmarkdown that allows newlines, the use of variables and nested functions as well as Markdown and Latex commands for outputting pdf's. The function would be used to, for example, generate formatted sections in Rmarkdown documents (I realize that I could use Latex' \titleformat{\section} to achieve this in the particular case of sections but I would also like to be able to display, for example, JSON data with a certain formatting in Rmarkdown).
Here is an example of a function that doesn't work but that will hopefully illustrate what I would like to achieve:
---
title: "Printing from function with newlines and escaped Markdown/Latex commands"
author: "Jono3030"
output: pdf_document
---
thirdLineFunction <- function() {
thirdLine <- "**This is the third line in bold**"
return(thirdLine)
}
newLinePrinting <- function(exampleVar) {
firstLine <- "This is the first line"
secondLine <- sprintf("This is the %s line", exampleVar)
thirdLine <- thirdLineFunction()
fourthLine <- "\\textit{This is the fourth line in italics}"
cat(firstLine, "\n\n", secondLine, "\n\n", thirdLine, "\n\n", fourthLine)
}
Using cat and including newline characters results in non of the strings being printed i.e. only the title and author appear in the pdf. Even if printing with cat works, however, Markdown and Latex code does not get escaped. Using print, sprintf or paste instead of cat does not print newlines and some of these methods include indices ([1] etc.) and quotations marks in the outputs which is not desired.
The desired output that renders correctly to a pdf from Rmarkdown would be:
This is the first line
This is the second line
**This is the third line in bold**
\textit{This is the fourth line in italics}
I also tried to print from the function with a for loop:
test <- function() {
o1 <- "This is text"
o2 <- "This is \\textbf{also} text"
o3 <- thirdLineFunction()
o4 <- "This is *text*"
newline <- ""
listvar <- c(o1, newline, o2, newline, o3, newline, o4)
for (i in listvar) {
print(noquote(i))
}
}
Although closer to what I want it didn't work either as I could not get rid of the indices:
[1] This is text
[1]
[1] This is \\textbf{also} text
[1]
[1] **This is the third line in bold**
[1]
[1] This is *text*
Using cat to omit the indices resulted in the Markdown and Latex commands not being escaped.
Using the above for loop with a combination of paste and cat didn't work either:
for (i in listvar) {
paste(i, collapse = '\n') %>% cat()
}
Of note might be that cat does work when I execute code in the console but the output does not show in the rendered pdf. I also tried to render to html which doesn't work either.
Again, eventually I would like to be able to print something like this using a function:
## Section Title
\vspace{1em}
\hrulefill
Or:
This is the **first** line printed from a JSON file
\vspace{1em}
This is the \textbf{second} line printed from a JSON file
\vspace{1em}
The output should then be rendered correctly into pdf, respecting the Markdown and Latex formatting.
Thank you in advance for your time and help!
I figured out a way to do what I wanted using paste():
stackOverflow <- function() {
paste(c(
"This is the **first** line printed from a JSON file",
"\\vspace{1em}",
"\n",
"This is the \\textbf{second} line printed from a JSON file",
"\n",
"\\vspace{1em}"
), collapse = "\n")
}
Putting the multiline output in a list nested in paste() using collapse = "\n" results in the following when executed:
[1] "This is the **first** line printed from a JSON file\n\\vspace{1em}\nThis is the \textbf{second} line printed from a JSON file\n\\vspace{1em}"
Which gets rendered correctly:
It's not perfect as Rmarkdown, for example, requires two spaces at the end or a blank line between text to put it in a new line hence why I added the extra "\n" characters. For now it works, however, so I'm marking it as the correct answer in the hopes that it will help others. If someone can come up with a better solution I'll happily mark theirs as correct.
Edit:
The extra line/two spaces required by markdown can, in most cases, be solved by collapsing with two line break characters like so: "\n\n"
This changes the above code to:
stackOverflow <- function() {
paste(c(
"This is the **first** line printed from a JSON file",
"\\vspace{1em}",
"This is the \\textbf{second} line printed from a JSON file",
"\\vspace{1em}"
), collapse = "\n\n")
}

Suppress messages in markdown, but not in R console

I currently use the following header:
```{r, message=FALSE}
foo <- function(x) message(x)
for(i in 1:10) foo(i)
```
Inside this code chunk, there is a loop over simulated scenarios, with message() function that prints status of currently executed scenario.
I would like to suppress those messages from display in RStudio and final HTML output, but I still want to control the simulation progress and see the message() output in console. Is this achievable? Maybe with other arguments/functions?
You can write/append status to a file (this is a workaround solution, there should be a more direct answer).
For example:
file <- file("status.txt", open = "wt")
sink(file, type = "message")
message("all good")
In this example message won't be displayed - it'll be written to a status.txt file.
In you're using specific function and iterating over a set you can try this example:
foo <- function(x) {
message(x)
}
file <- file("status.txt", open = "wt")
sink(file, type = "message")
for(i in 1:3) {
foo(i)
}
Function foo should return (message) value, however it appends it to a status.txt file.
You can track changes in status.txt file using bash tail command with -f argument. First send R to background and then use tail -f status.txt in your console.
One approach would be to put this in the start of your file.
mymessage <- function (text) {
if(knitr::opts_knit$get('out.format') != NULL) message(text)
}
There are various ways to know if you are within knitr, recent versions have knitr::is_latex_output and similar.

Inline knitr print code not printing

How do I fix this?
Inline `r 41`. What about `r print(42)`? Finally, `r I(print(43))`.
When I run this through knit2html(), it prints 42 and 43 to the R console. The HTML file that's produced is missing the 42.
Inline 41. What about ? Finally, 43.
I just found this: https://github.com/yihui/knitr/blob/master/NEWS.md
MINOR CHANGES
for inline R code, the value is returned only if the R code prints a visible value, e.g. \Sexpr{x <- 1} will be empty, and \Sexpr{pi} will return the value of pi
I think this change is a mistake. Please revert it. I have a function that does the printing. Do I really need to wrap it in I() every time I use it?
I could wrap the print statements inside the function in I(), but that's a hack and it doesn't even work too well. What if I am using a third party function that does the printing?
Here is what happens when I wrap print statements inside the function in I():
my_print = function () {
I(print(142))
}
my_cat = function () {
I(cat(143, "\n"))
}
Markdown:
What `r my_print()` about `r my_cat()` this?
```{r}
my_print()
```
```{r}
my_cat()
```
Output:
What 142 about this?
my_print()
## [1] 142
## [1] 142
my_cat()
## 143
## list()
So this fixes it for inline use, but breaks for chunk use. But only for print. Cat doesn't even work for inline.

How do I set conditional LaTeX code using R?

Suppose in my R/Sweave created LaTeX document, I want to have \subsection{Foo} if in my R code we have that x==1, whereas if x==2 in my R code I want \subsection{Bar} to be displayed.
How do I accomplish this? I know how to include R code by encapsulating it in <<>>= and # but I'm not sure how to do something such as the following (perhaps nonsensical) pseudo-code:
if(x==1)
Show \subsection{Foo} in LaTeX document
else if(x==2)
Show \subsection{Bar} in LaTeX document
What I also want to do that is very closely related is have subheading \subsection{z} in my LaTeX document, where z is defined strictly in my R code as some arbitrary string that I can toggle.
\Sexpr{} can evaluate expressions inline:
Show \subsection{\Sexpr{if(x==1) "Foo" else "Bar"}} in LaTeX document
\subsection*{\Sexpr{z}}
Use results=tex and cat the LaTeX code you want.
<<results=tex>>=
if(x==1) {
z <- "Foo"
} else if(x==2) {
z <- "Bar"
}
cat("\\subsection{", z, "}\n", sep="")
#

Sweave can't see a vector if run from a function?

I have a function that sets a vector to a string, copies a Sweave document with a new name and then runs that Sweave. Inside the Sweave document I want to use the vector I set in the function, but it doesn't seem to see it.
(Edit: I changed this function to use tempdir(() as suggested by Dirk)
I created a sweave file test_sweave.rnw;
%
\documentclass[a4paper]{article}
\usepackage[OT1]{fontenc}
\usepackage{Sweave}
\begin{document}
\title{Test Sweave Document}
\author{gb02413}
\maketitle
<<>>=
ls()
Sys.time()
print(paste("The chosen study was ",chstud,sep=""))
#
\end{document}
and I have this function;
onOK <- function(){
chstud<-"test"
message(paste("Chosen Study is ",chstud,sep=""))
newfile<-paste(chstud,"_report",sep="")
mypath<-paste(tempdir(),"\\",sep="")
setwd(mypath)
message(paste("Copying test_sweave.Rnw to ",paste(mypath,newfile,".Rnw",sep=""),sep=""))
file.copy("c:\\local\\test_sweave.Rnw",
paste(mypath,newfile,".Rnw",sep=""), overwrite=TRUE)
Sweave(paste(mypath,newfile,".Rnw",sep=""))
require(tools)
texi2dvi(file = paste(mypath,newfile,".tex",sep=""), pdf = TRUE)
}
If I run the code from the function directly, the resulting file has this output for ls();
> ls()
[1] "chstud" "mypath" "newfile" "onOK"
However If I call onOK() I get this output;
> ls()
[1] "onOK"
and the print(...chstud...)) function generates an error.
I suspect this is an environment problem, but I assumed because the call to Sweave occurs within the onOK function, it would be in the same enviroment, and would see all the objects created within the function. How can I get the Sweave process to see the chstud vector ?
Thanks
Paul.
I have similar problem. Eventually I found a work-around that "works for me", although it may not be the most elegant way to solve this issue.
Within my function, before 'Sweave' is executed, I put a statement to globally store the local environment:
temp <<- environment()
Using your code example it would look something like:
testFoo<-function(){
foo<-"My Test String"
temp <<- environment()
Sweave("test_sweave.Rnw")
require(tools)
texi2dvi(file = "test_sweave.tex", pdf = TRUE)
}
rm(foo) testFoo()
Then in the LaTeX file to be 'Sweaved' in the beginning of the first chunk I restore the necessary variables, but you can also use 'temp$foo' to access the 'foo' variable that was created within the function. This way I avoid globally storing multiple variables.
%
\documentclass[a4paper]{article}
\usepackage[OT1]{fontenc}
\usepackage{Sweave}
\begin{document}
\title{Test Sweave Document}
\author{Paul Hurley}
\maketitle
<<>>=
if(exists("foo", envir=temp)) { print(temp$foo) }
ls()
Sys.time()
#
\end{document}
Like I wrote above - this works, but is not very elegant.
OK, I realise that my initial ideas of a 'simple, self contained example' wasn't particularly simple or usefull. So I redid my example and got a sort of answer for myself, although I'd love someone to exaplain why and even suggest a better solution,
Here's my example test_sweave.Rnw file
%
\documentclass[a4paper]{article}
\usepackage[OT1]{fontenc}
\usepackage{Sweave}
\begin{document}
\title{Test Sweave Document}
\author{Paul Hurley}
\maketitle
<<>>=
if(exists("foo")){print(foo)}
ls()
Sys.time()
#
\end{document}
If I run this code;
testFoo<-function(){
foo<-"My Test String"
Sweave("test_sweave.Rnw")
require(tools)
texi2dvi(file = "test_sweave.tex", pdf = TRUE)
}
rm(foo) testFoo()
my resulting file does NOT contain the contents of the string foo.
> if (exists("foo")) {
+ print(foo)
+ }
> ls()
[1] "testFoo"
If I run this code (i.e, the same thing, just run directly)
rm(foo)
foo<-"My Test String"
Sweave("test_sweave.Rnw")
require(tools)
texi2dvi(file = "test_sweave.tex", pdf = TRUE)
my resulting file does contain the foo string
> if (exists("foo")) {
+ print(foo)
+ }
[1] "My Test String"
> ls()
[1] "foo" "testFoo"
and if I run this code
testBar<-function(){
foo<<-"My Test String"
Sweave("test_sweave.Rnw")
require(tools)
texi2dvi(file = "test_sweave.tex", pdf = TRUE)
}
rm(foo)
testBar()
My resulting file also contains the foo string
> if (exists("foo")) {
+ print(foo)
+ }
[1] "My Test String"
> ls()
[1] "foo" "testBar" "testFoo"
So, it seems that sweave runs in the global environment, not in the environment it was called from. This means the only way to pass variables to sweave when sweave is run from a function is to use the <<- operator to put the variable in the global environment. (I think).
Anyone else want to comment who knows more about environments ?

Resources