Inside the plot generated in a chunk in a knitr/LaTeX document I want to position a text string with a reference to a particular figure elsehwere in the document, something like "See Fig. 10", based on the label of a that particular figure, lets say "fig:sim1". So I wrote the following R function which reads the .aux file of the LaTeX-document I'm writing and extracts the counter of the figure matching a specific label
ref <- function(label) {
lines <- scan("mismatch-final.aux","character",sep="\n")
line <- grep(paste("\\{",label,"\\}",sep=""),lines,value=TRUE)
strsplit(strsplit(line,"\\{\\{")[[1]][2],"\\}\\{")[[1]][1]
}
I can then generate the desired text string from within the chunk and place it inside the plot with something like
text(5,10,paste("See Fig.~",ref("fig:sim1")))
This should work but perhaps there is a cleaner way of doing this? Also, is there a way to get at the .aux filename from within the chunk such that the ref function above would be made more general?
Another way to do that is to use the tikzDevice package and TikZ plots, so you can write raw LaTeX expressions in your plot, e.g
\begin{figure}
....
\caption{Simulation of something. \label{fig:sim1}}
\end{figure}
<<test, dev='tikz', external=FALSE>>=
plot(rnorm(10), rnorm(10))
text(0, 0, 'See Fig \\ref{fig:sim1}')
#
Depending on the complexity of your plot, this chunk may take a few seconds to compile each time. The plot is saved as a LaTeX file, and any LaTeX commands will work in it.
Related
I have a long .Rnw document which consists mostly of text (typeset in LaTeX) with a few chunks here and there. I have also written a chunk which outputs a specific figure. The figure contains a plot, the values for the plot are currently read from a .csv file and some parameters like colors defined manually within the chunk.
Now I want to have the same figure in a different place in the document, but with different values for the plot and a few other parameters different. Ideally, I would like to include the chunk as a child twice, and pass parameters to it somehow, including the name of the .csv to be used for the plot values. I would hate to copy paste the chunk code with hardcoded parameters, as it is complex enough that potential changes will be difficult to synchronize.
How can I do such "parameterized reuse" of chunks?
update
As requested, a small example
This is saved as include-chunk-reuse.Rnw
<<toReuse, echo=FALSE, result='asis'>>=
l <- 25
#
\newlength{\mylength}
\setlength{\mylength}{\Sexpr{l}pt}
%Omitted: a lot of complicated LaTeX commands
\rule{\mylength}{1pt}
This is the document which is supposed to reuse the chunk. It doesn't even compile, as it complains that the same label is used twice: Error in parse_block(g[-1], g[1], params.src) : duplicate label 'toReuse'
\documentclass{article}
\begin{document}
This is some text. And now comes a 25 pt wide line.
<<first-figure, child='include-chunk-reuse.Rnw'>>=
#
This is some text. The next line is also 25 pt wide. But I would like to call the chunk in a way which makes it 50 pt wide instead.
<<second-figure, child='include-chunk-reuse.Rnw'>>=
#
\end{document}
For the knitr part to work simply leave out the chunk-name in the child document, then you don't have the duplicated label and the knitr part works.
Passing Parameters does not really work as far as I know, but you can just set a global variable before including the child. (For example \Sexpr{l <- 200}
You are still redefining \mylength which is why LaTeX will throw an error, so move the first definition of \mylength from the child to the main document.
The example below demonstrates two ways to reuse and parametrize a chunk.
Reusing Chunks
The mechanism is explained here. Basically, the simplest way to reuse a chunk is to add another empty chunk with the same label. Alternatively, the chunk option ref.label lets a chunk inherit another chunks code.
Both approaches of reusing chunks are largely equivalent – with one exception: figures generated in chunks are saved as chunklabel-i.pdf, where i is the figure index counted by chunk. Therefore, if a chunk is reused by repeating its label, figure i from the second use will overwrite figure i from the first use. This is the reason why I use ref.label (and thus distinct chunk labels) in the example below (otherwise, the points on both plots would be green).
In the example below, I used eval = FALSE in order to prevent evaluation of the masterchunk where it is defined. An alternative would be to externalize the chunk and read it by read_chunk().
Parameterizing Chunks
The two most straightforward options to "pass" parameters to a chunk are
chunk options and
global variables
Also when reusing chunks, each use can set different chunk options. The example below exploits this to set different captions.
As all chunks run in the same environment, setting a variable in an early chunk affects subsequent chunks accessing this variable. In the example below, mycolor is modified this way.
\documentclass{article}
\begin{document}
<<masterchunk, eval = FALSE>>=
plot(1:10, col = mycolor)
#
<<config1>>=
mycolor <- "red"
#
<<use1, ref.label = "masterchunk", fig.cap = "Red dots">>=
#
<<config2>>=
mycolor <- "green"
#
<<use2, ref.label = "masterchunk", fig.cap = "Green dots">>=
#
\end{document}
I am using knitr for a report wherein I have a lot of inline output text, mostly numeric values, using \Sexpr{}. I want to highlight All these inline outputs in my generated pdf.
Example code:
\documentclass[12pt]{article}
\begin{document}
<<echo=FALSE, include=FALSE>>=
N <- 100 # Total
N_f <- 60 # Women
#
There were \Sexpr{N} people in the company, \Sexpr{N_f} women and \Sexpr{N - N_f} men.
\end{document}
Hence, in the output all the number should be highlighted, i.e. with a shaded background (similar to using with \hl{} with the \usepackage{soul}).
It seems to me that the solution would use one of the inline output hooks. Another possibility might be to write a LaTeX function which search all the \Sexpr{...} expressions in the entire document and highlights them in the generated pdf. I am still learning and can not figure out how to implement these.
Thanks for any help or hints.
Note: The knitr page by yihui talks about manipulation of the numeric value (scientific notation, digits after decimal points) which I have got covered.
The output hook inline can be used to style output from \Sexpr{}. This is as simple as
knit_hooks$set(inline = function(x) { sprintf("\\textbf{%s}", x)})
Just define an arbitrary function that takes an argument x and returns the string to be printed. In this example I used \textbf to make the output bold, but this can be extended to any LaTeX commands.
In this answer, Yihui suggests an improvement that still takes the default inline hook into account. This ensures rounding as usually performed by the default hook:
hook_inline <- knit_hooks$get('inline')
knit_hooks$set(inline = function(x) { sprintf("\\textbf{%s}", hook_inline(x))})
I am looking for a way to put inline latex code into a R code chunk in Knitr.
Here is my example code from the knitr example site :
\documentclass{article}
\begin{document}
Example text outside R code here; we know the value of pi is \Sexpr{pi}.
<<my-label, echo=FALSE, eval=TRUE>>=
set.seed(1213) # for reproducibility
x = cumsum(rnorm(100))
m <- mean(x) # mean of x
print(m)
cat(m)
plot(x, type = 'l') # Brownian motion
#
\textit{Mean is :} \textbf{\Sexpr{m}}
\end{document}
For something simple like this is I could use result='asis' but for a more complicated piece of code, where you want to periodically write the result out to the document, (especially you have complex ggplot graphs), that solution does not work very well.
In the given example, I have 3 queries :
How would I use inline latex code for the output from line 8, in case I wanted to color, bold etc. that text.
Can one eliminate the grey box that appears when we use the cat or print command.
Can the numbering which appears with the print command, which is eliminated with the cat command be eliminated for the print command as well, since print has many variants in many packages for data frames data tables etc. and might be more commonly used to print a portion of data.
In summary, I am mainly looking for the inverse of line 12 in the code.
I have also unsuccessfully tried knit_print with printr, and asis_output, in lieu of print. Although I may have been incorrectly using them.
Thanks!
My chunk in Sweave:
<<fig=TRUE,echo=FALSE>>=
for(i in 1:10) {
plot(rep(i,10))
dev.new()
}
#
In the resulting pdf I get only one plot (from the first iteration). I would like to have all of the 10 plots printed. What am I doing wrong? I tried replacing dev.new() with frame() and plot.new() but nothing happened.
As #rawr suggests the easiest solution is to switch to knitr (there's really no reason at all not to!) and put fig.keep="all" in your code chunk options (if you switch to knitr you don't need fig=TRUE any more ... including figures works automatically, fig.keep="none" is the analogue of fig=FALSE)
Alternatively, if you want to stick with vanilla Sweave, check the Sweave manual p. 17:
A.9 Creating several figures from one figure chunk does not work
Consider that you want to create several graphs in a loop similar to
<<fig=TRUE>>
for (i in 1:4) plot(rnorm(100)+i)
#
This will currently not work, because Sweave allows only one graph per figure chunk. The simple reason is that Sweave opens a postscript device before executing the code and closes it
afterwards. If you need to plot in a loop, you have to program it along the lines of
<<results=tex,echo=FALSE>>=
for(i in 1:4){
file=paste("myfile", i, ".eps", sep="")
postscript(file=file, paper="special", width=6, height=6)
plot(rnorm(100)+i)
dev.off()
cat("\\includegraphics{", file, "}\n\n", sep="")
}
#
My chunk in Sweave:
<<fig=TRUE,echo=FALSE>>=
for(i in 1:10) {
plot(rep(i,10))
dev.new()
}
#
In the resulting pdf I get only one plot (from the first iteration). I would like to have all of the 10 plots printed. What am I doing wrong? I tried replacing dev.new() with frame() and plot.new() but nothing happened.
As #rawr suggests the easiest solution is to switch to knitr (there's really no reason at all not to!) and put fig.keep="all" in your code chunk options (if you switch to knitr you don't need fig=TRUE any more ... including figures works automatically, fig.keep="none" is the analogue of fig=FALSE)
Alternatively, if you want to stick with vanilla Sweave, check the Sweave manual p. 17:
A.9 Creating several figures from one figure chunk does not work
Consider that you want to create several graphs in a loop similar to
<<fig=TRUE>>
for (i in 1:4) plot(rnorm(100)+i)
#
This will currently not work, because Sweave allows only one graph per figure chunk. The simple reason is that Sweave opens a postscript device before executing the code and closes it
afterwards. If you need to plot in a loop, you have to program it along the lines of
<<results=tex,echo=FALSE>>=
for(i in 1:4){
file=paste("myfile", i, ".eps", sep="")
postscript(file=file, paper="special", width=6, height=6)
plot(rnorm(100)+i)
dev.off()
cat("\\includegraphics{", file, "}\n\n", sep="")
}
#