Run Sweave or knitr with objects from existing R session - r

Suppose I have an object x in my current session:
x <- 1
How can I use this object in an Sweave or knitr document, without having to assign it explicitly:
\documentclass{article}
\begin{document}
<<>>=
print(x)
#
\end{document}
Reason I am asking is because I want to write an R script that imports data and then produces a report for each subject using an Sweave template.

I would take a slightly different approach to this, since using global variables reduces the reproducibility of the analysis. I use brew + sweave/knitr to achieve this. Here is a simple example.
# brew template: "template.brew"
\documentclass{article}
\begin{document}
<<>>=
print(<%= x %>)
#
\end{document}
# function to write report
write_report <- function(x){
rnw_file <- sprintf('file_%s.rnw', x)
brew::brew('template.brew', rnw_file)
Sweave(rnw_file)
tex_file <- sprintf('file_%s.tex', x)
tools::texi2pdf(tex_file, clean = TRUE, quiet = TRUE)
}
# produce reports
dat <- 1:10
plyr::l_ply(dat, function(x) write_report(x))

I think it just works. If your Sweave file is named "temp.Rnw", just run
> x <- 5
> Sweave("temp.Rnw")
You'll have to worry about naming the resulting output properly so each report doesn't get overwritten.

Both Sweave and knitr makes use of the global environment (see globalenv()) when evaluating R code chunks, so whatever in your global environment can be used for your document. (Strictly speaking, knitr uses the parent frame parent.frame() which is globalenv() in most cases)

Another option I have used in the past is to have the Sweave code open a file,
in my R session
write.csv(x, "tabletoberead.csv")
in my sweave document
<<label=label, echo=FALSE>>=
datatobeused<-read.csv("tabletoberead.csv")
...more manipulations on data ....
#
Obviously you should include code to stop if the file can't be found.

Related

Conditionally print text or show graph in beamer presentation

I have some difficulties implementing a (beamer) presentation. Everything works fine until I include a function which checks a specific condition and accordingly returns the output (graph - print text). Without that function it works fine. So how can I either graph or print the output?
\documentclass[10pt]{beamer}
\usepackage[T1]{fontenc}
\begin{document}
\begin{frame}{test}
<<echo=FALSE, fig.height = 4>>=
dates <- seq(as.Date("2015-02-13"), as.Date("2015-02-22"), by = "days")
b <- c(1,1,1,1,2,2,3,3,3,0)
c <- c(20,30,26,20,30,40,5,10,4,0)
d <- c(11,2233,12,2,22,13,23,23,100,0)
df <- data.frame(dates,b,c,d)
plot(df)
test <- function(df) {
if(sum(tail(df[2:ncol(df)], 1)) > 0) { # check only last date
return(plot(df))
} else {
print("Have a nice day!")
}
}
test(df)
#
\end{frame}
\end{document}
knitr wraps output in verbatim as can be seen from the TEX that the Rnw in the question produces:
\begin{frame}{test}
\begin{knitrout}
\definecolor{shadecolor}{rgb}{0.969, 0.969, 0.969}\color{fgcolor}\begin{kframe}
\begin{verbatim}
## [1] "Have a nice day!"
\end{verbatim}
\end{kframe}
\includegraphics[width=10cm,height=8cm]{figure/unnamed-chunk-2-1}
\end{knitrout}
\end{frame}
However:
It is straightforward to use Sweave or knitr with beamer; the only thing you need to be careful of is you have to add the fragile option to the frames that contain verbatim code. [Source]
Therefore, the frame needs the fragile option:
\begin{frame}[fragile]{test}
With fragile make sure not to indent \end{frame}. (This happened to me after copying the code from the question …)

If-Else Statement in knitr/Sweave using R variable as conditional

I am currently using knitr in R and RStudio to produce a LaTeX output. My code is a .Rnw file (called, say, testKnitr.Rnw) that is compiled to a pdf file with:
knit("testKnitr.Rnw") // in RStudio
pdflatex testKnitr.tex // in terminal
I would like to use an if-else syntax in LaTeX so that, depending on the value of an R variable, one of two LaTeX text paragraphs are output. In these LaTeX paragraphs, I would like to use expressions like \Sexpr{} and and \ref.
I have a minimal-working-example that is based on the second answer to a similar question posted here:
How to write an if-then statement in LaTeX using the value of an R variable in knitr/Sweave
Here is the MWE:
\documentclass{article}
\begin{document}
<<include=FALSE>>=
library(knitr)
opts_chunk$set(
concordance=TRUE
)
#
<<condition, include=FALSE, echo=FALSE>>=
x<- rnorm(1)
if(x>0){
text <- "This means x value of \Sexpr{x} was greater than 0"
}else{
text <- "This means x value of \Sexpr{x} was less than 0"
}
#
Testing the code:
<<print, results='asis', echo=FALSE>>=
cat(text)
#
\end{document}
Ideally, the intended output of the above MWE would a report with one line that contained something like:
"This means x value of 0.87 was greater than 0"
or
"This means x value of -0.87 was less than 0"
Before answering this question, I would like to take a look at the meta-question of whether this should be done.
Should we do it?
I don't think so. What we are basically doing here is using knitr to insert \Sexpr{x} in a document and then interpret \Sexpr{x}. There are no (obvious) reasons why we should take this detour instead of inserting the value of x directly to the document.
How to do it?
The following minimal example shows how it could be done anyways:
\documentclass{article}
\begin{document}
<<setup, echo = FALSE>>=
library(knitr)
knit_patterns$set(header.begin = NULL)
#
<<condition, echo=FALSE>>=
x <- rnorm(1)
if (x > 0) {
text <- "This means x value of \\Sexpr{x} was greater than 0"
} else {
text <- "This means x value of \\Sexpr{x} was less than 0"
}
#
Testing the code:
<<print, results='asis', echo=FALSE>>=
cat(text)
#
\end{document}
Two things are important here:
We need to escape the backslash in \Sexpr, resulting in \Sexpr.
We need to set knit_patterns$set(header.begin = NULL).
To compile the document:
Save it as doc.Rnw.
Then execute:
knitEnv <- new.env()
knit(input = "doc.Rnw", output = "intermediate.Rnw", envir = knitEnv)
knit2pdf(input = "intermediate.Rnw", output = "doc_final.tex", envir = knitEnv)
What happens?
The first call of knit generates intermediate.Rnw with the following content:
\documentclass{article}
\begin{document}
Testing the code:
This means x value of \Sexpr{x} was less than 0
\end{document}
You should note that knitr didn't include any definitions, commands etc. as usual to the LaTeX code. This is due to setting header.begin = NULL and documented here. We need this behavior because we want to knit the resulting document again in the second step and LaTeX doesn't like it when the same stuff is defined twice.
Creating the new environment knitEnv and setting it as envir is optional. If we skip this, the variable x will be created in the global environment.
In the second step we use knit2pdf to knit intermediate.Rnw and immediately generate a PDF afterwards. If envir was used in the first step, we need to use it here too. This is how x and it's value are conveyed from the first to the second knitting step.
This time all the gory LaTeX stuff is included and we get doc_final.tex with:
\documentclass{article}\usepackage[]{graphicx}\usepackage[]{color}
%% maxwidth is the original width if it is less than linewidth
%% otherwise use linewidth (to make sure the graphics do not exceed the margin)
\makeatletter
\def\maxwidth{ %
\ifdim\Gin#nat#width>\linewidth
\linewidth
\else
\Gin#nat#width
\fi
}
\makeatother
%% more gory stuff %%
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
\begin{document}
Testing the code:
This means x value of \ensuremath{-0.294859} was less than 0
\end{document}

knitr: less/greater than sign displayed as (¡) and (¿)

I'm a beginner in using knitr to generate a report.
I have a R script (see below for an example; BTW I'm using RStudio for all of this) that runs without error and the output is a data frame. My rnw.file looks like this:
% !Rnw weave = knitr
\documentclass[a4paper]{article}
\begin{document}
<<echo=FALSE,message=FALSE>>=
source("test.R")
kable(test.mat)
#
\end{document}
which displays the table quite nicely. The only problem I have is with the ">" (greater than) sign in the last column which is shown as "¿".
In found something about using
\usepackage[T1]{fontenc}
but this doesn't seem to do the trick here. Having included this, I can start compiling the script but after 10 minutes or so (and before it only took me some seconds to compile) I run into an error (exit code: 1).
Thanks in advance!
R.script (saved as "test.R"):
temp <- 12
test.mat <- as.data.frame(matrix(NA,ncol=2,nrow=1))
test.mat$V1 <- 2
test.mat$V2 <- paste(temp,"subjects > 28 days",sep=" ")
> is a mathematical symbol and as so it is not recognized unless it is not embedded in a a mathematical environment (inline or as a bloc.)
Try this code.
$>$
A (not so elegant) solution
The behavior of kable remains strange. After I've analyzed the latex code that it produces I've tried this solution, which is not so elegant, but it works. Hoping that some other users will provide more efficient solutions. Here is my code.
% !Rnw weave = knitr
\documentclass[a4paper]{article}
\begin{document}
<<echo = F, message = FALSE>>=
source("test.R")
aa1
#
\end{document}
where the test.R is:
temp <- 12
test.mat <- as.data.frame(matrix(NA,ncol=2,nrow=1))
test.mat$V1 <- 2
test.mat$V2 <- paste(temp,"subjects > 28 days",sep=" ")
aa <- kable(test.mat, format = "latex")
aa1 <- gsub(">", "$>$", aa)
and here is the result:
I can't explain why it is working now, but here is what I found I should use in the preambel:
\usepackage{lmodern}
\usepackage[T1]{fontenc}
Found this in another thread (not really related to my question), but now I get what I want in the R output (no changes required in the R.script) as well as in the pdf.

knitr: starting a fresh R session to clear RAM

I sometimes work with lots of objects and it would be nice to have a fresh start because of memory issues between chunks. Consider the following example:
warning: I have 8GB of RAM. If you don't have much, this might eat it all up.
<<chunk1>>=
a <- 1:200000000
#
<<chunk2>>=
b <- 1:200000000
#
<<chunk3>>=
c <- 1:200000000
#
The solution in this case is:
<<chunk1>>=
a <- 1:200000000
#
<<chunk2>>=
rm(a)
gc()
b <- 1:200000000
#
<<chunk3>>=
rm(b)
gc()
c <- 1:200000000
#
However, in my example (which I can post because it relies on a large dataset), even after I remove all of the objects and run gc(), R does not clear all of the memory (only some). The reason is found in ?gc:
However, it can be useful to call ‘gc’ after a large object has
been removed, as this may prompt R to return memory to the
operating system.
Note the important word may. R has a lot of situations where it specifies may like this and so it is not a bug.
Is there a chunk option according to which I can have knitr start a new R session?
My recommendation would to create an individual .Rnw for each of the major tasks, knit them to .tex files and then use \include or \input in a parent.Rnw file to build the full project. Control the building of the project via a makefile.
However, to address this specific question, using a fresh R session for each chunk, you could use the R package subprocess to spawn a R session, run the needed code, extract the results, and then kill the spawned session.
A simple example .Rnw file
\documentclass{article}
\usepackage{fullpage}
\begin{document}
<<include = FALSE>>=
knitr::opts_chunk$set(collapse = FALSE)
#
<<>>=
library(subprocess)
# define a function to identify the R binary
R_binary <- function () {
R_exe <- ifelse (tolower(.Platform$OS.type) == "windows", "R.exe", "R")
return(file.path(R.home("bin"), R_exe))
}
#
<<>>=
# Start a subprocess running vanilla R.
subR <- subprocess::spawn_process(R_binary(), c("--vanilla --quiet"))
Sys.sleep(2) # wait for the process to spawn
# write to the process
subprocess::process_write(subR, "y <- rnorm(100, mean = 2)\n")
subprocess::process_write(subR, "summary(y)\n")
# read from the process
subprocess::process_read(subR, PIPE_STDOUT)
# kill the process before moving on.
subprocess::process_kill(subR)
#
<<>>=
print(sessionInfo(), local = FALSE)
#
\end{document}
Generates the following pdf:

Including several tables in tex format in my main document

Is there a way to generate tables in tex format in R and then call them in my *.rnw file
I have to geenerate a lot of tables using some userdefined function and then use them in my latex file through sweave/knitr.
Here is a simplified example to illustrate my point...
Data:
x1 <- round(rnorm(10),2)
x2 <- sample(c('a','b','c'),10,replace=TRUE)
data1 <- cbind(x1,noquote(x2));data1 <- as.data.frame(data1)
names(data1)=c('X1','X2')
Now I want to put this data1 in a tex file as follows
latex(data1,file='myfile.tex')
When running the above in my sweave document R-studio was getting stuck in the sense that the process would not end.
I get the following error
No file file1170690e2c79.aux.
*geometry* driver: auto-detecting
*geometry* detected driver: dvips
[1] (C:\Users\~~~\AppData\Local\Temp\RtmpeuvW08\file1170690e2c79.aux) )
Output written on file1170690e2c79.dvi (1 page, 604 bytes).
Transcript written on file1170690e2c79.log.
So, I used the following
sink('myfile.tex')
latex(data1,file='')
sink()
I guess there might be a better way. I do not not what mistake I am doing in the latex command.
I would appreciate if someone can help me with this by providing me a better approach
Here is my sweave file
\documentclass{article}
\usepackage{ctable}
\title{Untitled}
\begin{document}
\maketitle
<<somechunk,results=tex,echo=FALSE>>=
x1 <- round(rnorm(10),2)
x2 <- sample(c('a','b','c'),10,replace=TRUE)
data1 <- cbind(x1,noquote(x2));data1 <- as.data.frame(data1)
names(data1)=c('X1','X2')
sink('myfile.tex')
latex(data1,file='')
sink()
#
Here is my table 1 \include{myfile}
\end{document}
As suggested in the other answers, the easiest
(with Hmisc::latex or xtable)
is usually to generate the LaTeX code only when needed.
If this is not possible, the following should work:
tmp <- latex(data1,file='myfile.tex')
What happens is that latex creates the file
and returns an object of class latex.
The print method is then called, but it tries to compile the file
and display the results, which is not desired in your case.
Assigning the result to a variable (which will not be used),
or wrapping the call in invisible, suppresses the call to print.
invisible( latex(data1,file='myfile.tex') )
You could use the xtable package:
\documentclass{article}
\usepackage{ctable}
\begin{document}
<<somechunk,results=tex,echo=FALSE,results=hide>>=
library(xtable)
x1 <- round(rnorm(10),2)
x2 <- sample(c('a','b','c'),10,replace=TRUE)
data1 <- cbind(x1,noquote(x2));data1 <- as.data.frame(data1)
names(data1)=c('X1','X2')
#
Here is my table 1:
<<results=tex, echo=FALSE>>=
xtable(data1)
#
\end{document}

Resources