Can you make inline chunks in knitr evaluate last? - r

I am using knitr to write a manuscript.
I am using inline chunks to make sure the text matches my actual data.
For example "I performed regression on \rinline{nrow(df)} data points."
However, this information is needed in the abstract and other early parts of the text, while df is created by code that is next to the methods section that explains how it is created.
Can I force all inline chunks to evaluate last?
To be clear here is a markdown example.
Abstract
---------
My study is really interesting.
I performed regression on `r nrow(df)` data points.
Methods
--------
I used simulated data drawn from a normal distribution.
```{r data}
df <- data.frame(x = rnorm(10), y = rnorm(10))
```
The second sentence in the abstract should read "I performed regression on 10 data points."

In writing the MRE I discovered the answer.
If you knit the document in an R session, the variables will be saved to the global namespace.
Knitting the document a second time will fill in the inline chunks.
I didn't get any errors in the first knit.
So you do need to check that the final document does contain all the inline values.

Related

`bookdown`/`rmarkdown`/`knitr`: Non-code sequential processing howto?

Programatically my bookdown project proceeds as follows:
Reading in raw data - produces all kind of stats.
Data preprocessing (logarithmization, normalization, imputation) - produces various plots for monitoring the population-level defects incurred.
PCA for analysis QC - produces plots for PCA and loadings-dominating data points.
Differential expression analysis - produces volcano plots and plots characterizing prominent differentially expressed features.
Overrepresentation analysis of the differentially expressed features from 4. in various biological ontology systems - produces example bar plots for enriched categories.
I have analysis and narrative nicely integrated using bookdown, enabling efficient on fly discarding of temporary (sizable) data sets/ggplot2 objects (pre/post transformation data etc.).
HOWEVER: The target audience is mostly/only interested in 4. & 5., leading me to the aspired to following structure:
4., 5., Appendix(1., 2., 3.)
Is there any other way but precomputing 1.-5. and then revisiting in the targeted order - I would prefer to avoid accumulating all those ggplot2 objects in memory if at all possible.
You could do the following:
Split steps 1-3 and 4-5 into two speparate *.Rmd files, say 123.Rmd and 45.Rmd.
Add a code chunk to the beginning of 45.md that knits 123.Rmd to 123.md:
```{r knit123, include = FALSE}
knitr::knit("123.Rmd", output = "123.md")
```
This will generate the output of steps 1-3 in Markdown and make all the objects created thereby available to steps 4-5.
Add a code chunk to the end of 45.Rmd that reads 123.md prints its content:
```{r include123, results = "asis"}
cat(readLines("123.md"), sep = "\n")
```
The results = "asis" will prevent any further processing as it is already valid Markdown.
Knit 45.Rmd to whatever target format you want.
edit (1):
TL;DR: Instead of storing the object from steps 1-3 in memory throughout steps 4-5 in order to print them afterwards, print them first and store the results on disk.
edit (2):
Since you explicitely mentioned bookdown: I would not be surprised if there was a YAML option to include a Markdown file at the end of the knitting process (something like include-after: 123.md); but I don't know for sure from the top of my head and I'm too lazy to look it up myself. ;-)

Conditional output of dynamic text in a LaTeX knitr document

I'd like to print a few sentences in a knitr LaTeX doc (.Rnw), but only if some data exists. Those sentences are mostly text, but with some R.
Example:
A chi-squared test of your observed sizes has a p-value of
\Sexpr{format(calculated_chisq$p.value,digits=3,scientific=F)}.
A p-value below 0.05 means you should be concerned that your
groups are broken. The lower the p-value, the more worried you
should be.
I tried a chunk with results='asis', but I think the chunk is interpreted as R.
I tried print() and paste() with R. It's ugly, but it works. However, it puts extra text in that seems to correspond to the R prompt.
Is there a nice way to do this?
This is related, but different. This is the same, but unanswered.
This question is closely related to that question, but not duplicate I think: The accepted answer there translates into an ugly \Sexp monster with a condition inside. The code will be neither nice to read nor to write.
My own answer there is also not applicable because 1) the asis engine does not allow for dynamic elements in the text and 2) because output from the asis gets a gray background color in RNW documents.
I suggest the following solution:
\documentclass{article}
\begin{document}
<<>>=
x <- rnorm(1)
#
The value of $x$ is \Sexpr{x}.
<<echo=FALSE, results = "asis">>=
pattern <- "This will only be displayed if $x$ is positive. The value of $x$ is %.2f."
if (x > 0) cat(sprintf(pattern, x))
#
\end{document}
The conditional output is easy to read and write (pattern) and the dynamic elements are inserted via sprintf.

Include same chunk twice with different paramters

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}

inline Latex code inside knitr R block

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!

How to write an article with an abstract referencing data that has not yet been calculated?

UPDATE: Seems like my question is actually a very near duplicate of this question
and according to that thread, there is currently no "easy" solution. However, that question is over a year old now, and the time may have changed (one can hope!).
My original question follows:
I'm thinking that I need some kind of mechanism to re-order the text and or R chunks in the document as it is being knit. What I want to be able to do is to write an "article" style document with an abstract and summary at the beginning, before I get into any R code, but that contains "forward"-references to things that will be calculated in the R code.
So my exec summary at the beginning might be
We found a `r final_correlation/100`% correlation between x and y...
but "final_correlation" will be calculated at the back end of the document as I go through all of the steps of the reproducible research.
Indeed, when I read about reproducible research, I often see comments that the documentation can often be better presented out-of programming sequence.
I believe that in other literate programming frameworks the chunks can be tangled into a different order from that in which they were presented. How can I achieve that in knitr? Or is there some other completely different workflow or pattern I could adopt to achieve the outcome I want?
There is no way to define the order to evaluate all the code chunks in knitr at the moment. One idea I can think of is to write the abstract in the end of the article, and include it in the beginning. An outline:
article.Rmd
abstract.Rmd
In article.Rmd:
Title.
Author.
Abstract.
```{r echo=FALSE, results='asis'}
if (file.exists('abstract.md')) {
cat(readLines('abstract.md'), sep = '\n')
} else {
cat('Abstract not ready yet.')
}
```
More code chunks.
```{r}
x <- 1:10
y <- rnorm(10)
final_correlation <- cor(x, y)
```
Body.
```{r include=FALSE}
knitr::knit('abstract.Rmd') # generates abstract.md
```
In abstract.Rmd:
We found a `r final_correlation/100`% correlation between x and y...

Resources