When you use inline code in an R Markdown document, the code is evaluated and the output is incorporated into the text. For example,
The sum of 2 and 2 is `r 2+2`.
This will generate the following text in the .nb.html file:
The sum of 2 and 2 is 4.
That text is not styled or tagged in any way in the HTML output, so there is no way to apply CSS.
But I'd like to be able to see in the HTML document if text appears "as is" or if it was processed through inline code. In other words, I want to know see a difference in the appearance of the number 4 if I write
The sum of 2 and 2 is `r 2+2`.
versus
The sum of 2 and 2 is 4.
Is there any way to do this?
(The use case here is that I have students who are supposed to use inline code in their assignments, but if I'm looking at the .nb.html file and not the .Rmd file, I can't tell if they just manually typed in an answer without using code to generate it.)
EDIT: My original question said R Markdown, and there is a good solution to that question below. However, I need this to work in an R Notebook, and it seems that knit_hooks$set is ignored when creating the HTML file.
One possible way is using knitr::knit_hooks$set.
---
title: "Untitled"
author: "Shafayet Khan"
date: "2022-07-31"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
random_class <- paste0("class-", round(runif(1, 200, 2000)))
styleIt <- function(x) {
paste0("<span class='", random_class, "' style=\"color: red;\">", x,"</span>")
}
knitr::knit_hooks$set(inline = styleIt)
```
## R Markdown
### inline code
The sum of 2 and 2 is `r 2+2`
### not inline code
The sum of 2 and 2 is 4.
### Manually styled
The sum of 2 and 2 is <span style="color: red;">4</span>
When rendered, it looks like
Now note that the students always can use the span tag to get the same color as the inline code, so to make a difference, I have used a randomly generated class and used that for inline code, so when you have the HTML file, span tag for an inline code should have a randomly generated class name like class-672 while manually typed and colored code will unlikely have that same class name. Hope this helps.
Related
This question already has answers here:
How to request an early exit when knitting an Rmd document?
(2 answers)
Closed 3 years ago.
I do not have code for this question, and hope I can explain it.
While I am editing my rmarkdown file, I would like to knit it to see what it looks like until this point. I only want to see what it looks like until this point without knitting the whole file every time. I am wonder if we can insert a mark or something, so the rest of the file will be ignored or taken as plain text.
I have tried to add ````. It changed the color of the rest of text to orange, but still ran the inline code in it.
```{r setup,echo=FALSE}
run this
```
Chapter 1 with inline code `r code` and text,
edit this `r code`, knit until this point ignoring the rest:
Chapter 2.... ... Chapter 10 with a lot of inline code.
In Rmarkdown, you have a code chunck as
```{r [options]}
your code
```
For options you have eval,echo,messages, etc., but the beauty is that they are passed as render works though it. So you should be able to do something akin to:
```{r setup,echo=FALSE}
run this
```
I am doing code stuff! *Yeah*
```{r load_data}
More code
evalfromhere=FALSE
```
```{r step2b,eval=evalfromhere}
Doesn't work yet
```
```{r name2,eval=evalfromhere}
Also not yet
```
Once you are satisfied, set evalfromhere to TRUE, or remove the chunk options as you go along.
Rmarkdown is based on knitr, so read these documentations: https://yihui.name/knitr/options/
I'm creating a document in which I repeat the same formatting multiple times. So I want to automate the process using the for loop in R. Here's a simple example.
Assume, I have an R code that computes some information for all cut values in ggplot2::diamonds dataset, which I want then to print in my document in five separate sections (one section per cut):
library(knitr); library(data.table)
dt <- data.table(ggplot2::diamonds)
for (cutX in unique(dt$cut)) {
dtCutX <- dt[cut==cutX, lapply(.SD,mean), .SDcols=5:7]
#### START of the Rmd part that needs to be printed
# Section: The Properties of Cut `cutX`
<!-- NB: This is the Section title in Rmd format, not the comment in R format ! -->
This Section describes the properties of cut `r cutX`. Table below shows its mean values:
`r knitr::kable(dtCutX)`
The largest carat value for cut `r cutX` is `r dt[cut=='Ideal', max(carat)]`
#### END of the Rmd part that needs to be printed
}
How do I do that?
I.e., How do I insert inside my main Rmd code an R code that tells it to insert other Rmd codes (in a for loop) - to produce automatically five Sections for five types of diamond cuts?
PS.
I found these related posts:
Reusing chunks in Knitr and
Use loop to generate section of text in rmarkdown
but was not able yet to recreate the solution for the above example.
For this kind of task, you can use glue package to evaluate R expressions inside character strings.
Here's an Rmd file that answer your question:
---
title: "Untitled"
output: html_document
---
```{r echo=FALSE, results='asis'}
library(data.table)
dt <- data.table(ggplot2::diamonds)
for (cutX in unique(dt$cut)) {
dtCutX <- dt[cut==cutX, lapply(.SD,mean), .SDcols=5:7]
cat("\n\n# Section: The Properties of Cut `cutX`\n")
cat(glue::glue("This Section describes the properties of cut {cutX}. Table below shows its mean values:\n"))
print(knitr::kable(dtCutX))
cat(glue::glue("\n\nThe largest carat value for cut {cutX} is {dt[cut=='Ideal', max(carat)]}\n"))
}
```
Is there anyway to format code in the "code" format offered by many websites like Stackoverflow in R Markdown.
I want to be able to do something like the following:
Any model that takes the form income ~ education + parental_income
...
I want to emulate that greyed out text in R markdown for ease of readability when I eventually knit the document.
One can use backticks or indenting by 4 spaces to generate the equivalent of the HTML <code> </code> tag block. Here is an Rmd document illustrating this behavior.
---
title: "Sample Document"
author: "bigNumber"
date: "12/5/2017"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
here is some example code written in R Markdown. If we want to enter a code block we use the backtick, such as `inc ~ ed + occ`.
If we want a code block with multiple lines, indenting by 4 spaces also works
# first line of code
for(i in 1:100) {
# do something here
}
More text after the code block ends.
...and the output. Unfortunately I have to include an image to show that it renders correctly.
```
If you'd rather not
indent your code block by four spaces, you can use
triple back-ticks on separate lines.
```
https://bookdown.org/yihui/rmarkdown/markdown-syntax.html#block-level-elements
html could work if you want to have a string with gray color as a background
Changing chunk background color in RMarkdown
When using knitr and rmarkdown together to create a word document you can use an existing document to style the output.
For example in my yaml header:
output:
word_document:
reference_docx: style.docx
fig_caption: TRUE
within this style i have created a default table style - the goal here is to have the kable table output in the correct style.
When I knit the word document and use the style.docx the tables are not stylized according to the table.
Using the style inspector has not been helpful so far, unsure if the default table style is the incorrect style to modify.
Example Code:
```{r kable}
n <- 100
x <- rnorm(n)
y <- 2*x + rnorm(n)
out <- lm(y ~ x)
library(knitr)
kable(summary(out)$coef, digits=2, caption = "Test Captions")
```
I do not have a stylized document I can upload for testing unfortunately.
TL;DR: Want to stylise table output from rmarkdown and knitr automatically (via kable)
Update: So far I have found that changing the 'compact' style in the docx will alter the text contents of the table automatically - but this does not address the overall table styling such as cell colour and alignment.
Update 2: After more research and creation of styles I found that knitr seems to have no problem accessing paragraph styles. However table styles are not under that style category and don't seem to apply in my personal testing.
Update 3: Dabbled with the ReporteRs package - whilst it was able to produce the tables as a desired the syntax required to do so is laborious. Much rather the style be automatically applied.
Update 4: You cannot change TableNormal style, nor does setting a Table Normal style work. The XML approach is not what we are looking for. I have a VBA macro that will do the trick, just want to remove that process if possible.
This is essentially a combination of the answer that recommends TableNormal, this post on rmarkdown.rstudio.com and my own experiments to show how to use a TableNormal style to customize tables like those generated by kable:
RMD:
---
output:
word_document
---
```{r}
knitr::kable(cars)
```
Click "Knit Word" in RStudio. → The document opens in Word, without any custom styles yet.
In that document (not in a new document), add the required styles. This article explains the basics. Key is not to apply direct styles but to modify the styles. See this article on support.office.com on Style basics in Word.
Specifically, to style a table you need to add a table style. My version of Word is non-English, but according to the article linked above table styles are available via "the Design tab, on the Table Tools contextual tab".
Choose TableNormal as style name and define the desired styles. In my experiments most styles worked, however some did not. (Adding a color to the first column and making the first row bold was no problem; highlighting every second row was ignored.) The last screenshot in this answer illustrates this step.
Save the document, e.g. as styles.docx.
Modify the header in the RMD file to use the reference DOCX (see here; don't screw up the indentation – took me 10 minutes find this mistake):
---
output:
word_document:
reference_docx: styles.docx
---
Knit to DOCX again – the style should now be applied.
Following the steps I described above yields this output:
And here a screenshot of the table style dialog used to define TableNormal. Unfortunately it is in German, but maybe someone can provide an English version of it:
As this does not seem to work for most users (anyone but me …), I suggest we test this systematically. Essentially, there are 4 steps that can go wrong:
Wrong RMD (unlikely).
Differences in the initially generated DOCX.
Differences in how the TableNormal style is saved in the DOCX.
Differences in how the reference DOCX is used to format the final DOCX.
I therefore suggest using the same minimal RMD posted above (full code on pastebin) to find out where the results start do differ:
My initially generated DOCX.
The same document with TableNormal added: reference.docx
The final document.
The three files are generated on the following system: Windows 7 / R 3.3.0 / RStudio 0.99.896 / pandoc 1.15.2 / Office 2010.
I get the same results on a system with Windows 7 / R 3.2.4 / RStudio 0.99.484 / pandoc 1.13.1 / Office 2010.
I suppose the most likely culprits are the pandoc and the Office versions. Unfortunately, I cannot test other configurations at the moment. Now it would be interesting to see the following: For users where it does not work, what happens …
… if you start from my initial.docx?
If that does not work, what if you use my reference.docx as reference document?
If nothing works, are there eye-catching differences in the generated XML files (inside the DOCX container)? Please share your files and exact version information.
With a number of users running these tests it should be possible to find out what is causing the problems.
This was actually a known issue. Fortunately, it was solved in v2.0 or later releases of pandoc.
And I have tested the newer version, and found that there is a newly-added hidden style called "Table". Following #CL.'s suggestions to change "Table" style in reference.docx will be okay now.
In addition, look at this entry of pandoc's v2.0 release notes:
Use Table rather than Table Normal for table style (#3275). Table Normal is the default table style and can’t be modified.
As of 2021, I could not get any of the other suggested answers to work.
However, I did discover the {officedown} package, which, amongst other things, supports the styling of tables in .docx documents. You can install {officedown} with remotes::install_github("davidgohel/officedown")
To use {officedown} to render .Rmd to .docx you must replace
output:
word_document
in your document header with
output:
officedown::rdocx_document
In addition to this the {officedown} package must be loaded in your .Rmd.
As with the word_document output format, {officedown} allows us to use styles and settings from template documents, again with the reference_docx parameter.
With a reference document styles.docx, a minimal example .Rmd may look like:
---
date: "2038-01-19"
author: "The Reasonabilists"
title: "The end of time as we know it"
output:
officedown::rdocx_document:
reference_docx: styles.docx
---
```{r setup, include = FALSE}
# Don't forget about me: I'm important!
library("officedown")
```
{officedown} allows us to go one step further and specify the name of the table style to use in the document's front matter. This table style could be a custom style we created in styles.docx, or it could be one of Word's in-built styles you prefer.
Let's say we created a style My Table:
We could tell {officedown} to use this table style in our front matter as:
output:
officedown::rdocx_document:
reference_docx: styles.docx
tables:
style: My Table
Putting this altogether, knitting the minimal .Rmd:
---
date: "2038-01-19"
author: "The Reasonabilists"
title: "The end of time as we know it"
output:
officedown::rdocx_document:
reference_docx: styles.docx
tables:
style: My Table
---
```{r setup, include = FALSE}
# Don't forget about me: I'm important!
library(officedown)
```
```{r}
head(mtcars)
```
Resulting in a .docx document which looks like:
TableNormal doesn't work for me too.
On my Dutch version of Word 2016 (Office 365), I found out that I could markup tables with the style Compact.
Input (refdoc.docx contains the Compact style):
---
title: "Titel"
subtitle: "Ondertitel"
author: "`r Sys.getenv('USERNAME')`"
output:
word_document:
toc: true
toc_depth: 2
fig_width: 6.5
fig_height: 3.5
fig_caption: true
reference_docx: "refdoc.docx"
---
And RMarkdown:
# Methoden {#methoden}
```{r}
kable(cars)
```
Output:
You need to have a reference_docx: style.docx which has "Table" style in it. (see #Liang Zhang's explanation and links above).
Create a basis reference document using pandoc (source). In command line (or cmd.exe on Windows) run:
pandoc -o custom-reference.docx --print-default-data-file reference.docx
In this newly created reference.docx file, find the table created (a basic 1 row table with a caption).
While the table is selected, click "Table Design" and find "Modify Table Style":
Modify the style of the table as you wish and use this reference document in your RMD document (see the first answer by #CL.).
Using this reference document, you can also change the table and figure caption styles.
I was able to get my word output to use a default table style that I defined in a reference .docx.
Instead of 'TableNormal', the table style it defaulted to was 'Table'.
I discovered this by knitting an rmarkdown with a kable.
---
date: "December 1, 2017"
output:
word_document:
reference_docx: Template.docx
---
`r knitr::kable(source)`
Then I took a look at that generated document's XML to see what style it had defaulted to.
require(XML)
docx.file <- "generated_doc.docx"
## unzip the docx converted by Pandoc
system(paste("unzip", docx.file, "-d temp_dir"))
document.xml <- "temp_dir/word/document.xml"
doc <- xmlParse(document.xml)
tblStyle <- getNodeSet(xmlRoot(doc), "//w:tblStyle")
tblStyle
I defined the 'Table' style to put some color and borders in the reference docx. This works for one standard table style throughout the document, I haven't found a way to use different styles throughout.
This stayed true even after I opened the reference doc and edited it.
I'm writing a report in R Markdown in which I don't want to print any of my R code in the main body of the report – I just want to show plots, calculate variables that I substitute into the text inline, and sometimes show a small amount of raw R output. Therefore, I write something like this:
In the following plot, we see that blah blah blah:
```{r snippetName, echo=F}
plot(df$x, df$y)
```
Now...
That's all well and good. But I would also like to provide the R code at the end of the document for anybody curious to see how it was produced. Right now I have to manually write something like this:
Here is snippet 1, and a description of what section of the report
this belongs to and how it's used:
```{r snippetName, eval=F}
```
Here is snippet 2:
```{r snippetTwoName, eval=F}
```
<!-- and so on for 20+ snippets -->
This gets rather tedious and error-prone once there are more than a few code snippets. Is there any way I could loop over the snippets and print them out automatically? I'm hoping I could do something like:
```{r snippetName, echo=F, comment="This is snippet 1:"}
# the code for this snippet
```
and somehow substitute the following result into the document at a specified point when it's knitted:
This is snippet 1:
```{r snippetName, eval=F}
```
I suppose I could write some post-processing code to scan through the .Rmd file, find all the snippets, and pull out the code with a regex or something (I seem to remember there's some kind of options file you can use to inject commands into the pandoc process?), but I'm hoping there might be something simpler.
Edit: This is definitely not a duplicate – if you read my question thoroughly, the last code block shows me doing exactly what the answer to the linked question suggests (with a slight difference in syntax, which could have been the source of the confusion?). I'm looking for a way to not have to write out that last code block manually for all 20+ snippets in the document.
This is do-able within knitr, no need to use pandoc. Based on an example posted by Yihui at https://github.com/yihui/knitr-examples/blob/master/073-code-appendix.Rnw
Set echo=FALSE throughout your document: opts_chunk$set(echo = FALSE)
Then put this chunk at the end to print all code:
```{r show-code, ref.label=all_labels(), echo = TRUE, eval=FALSE}
```
This will print code for all chunks. Currently they all show up in a single block; I'd love to figure out how to put in the chunk label or some other header... For now I start my chunks with comments (probably not a bad idea in any case).
Updated: to show only the chunks that were evaluated, use:
ref.label = all_labels(!exists('engine')) - see question 40919201
Since this is quite difficult if not impossible to do with knitr, we can take advantage of the next step, the pandoc compilation, and of pandoc's ability to manipulate content with filters. So we write a normal Rmd document with echo=TRUE and the code chunks are printed as usual when they are called.
Then, we write a filter that finds every codeblock of language R (this is how a code chunk will be coded in pandoc), removes it from the document (replacing it, here, with an empty paragraph) and storing it in a list. We then add the list of all codeblocks at the end of the document. For this last step, the problem is that there really is no way to tell a python filter to add content at the end of a document (there might be a way in haskell, but I don't know it). So we need to add a placeholder at the end of the Rmd document to tell the filter to add the R code at this point. Here, I consider that the placeholder will be a CodeBlock with code lastchunk.
Here is the filter, which we could save as postpone_chunks.py.
#!/usr/bin/env python
from pandocfilters import toJSONFilter, Str, Para, CodeBlock
chunks = []
def postpone_chunks(key, value, format, meta):
if key == 'CodeBlock':
[[ident, classes, keyvals], code] = value
if "r" in classes:
chunks.append(CodeBlock([ident, classes, keyvals], code))
return Para([Str("")])
elif code == 'lastchunk':
return chunks
if __name__ == "__main__":
toJSONFilter(postpone_chunks)
Now, we can ask knitr to execute it with pandoc_args. Note that we need to remember to add the placeholder at the end of the document.
---
title: A test
output:
html_document:
pandoc_args: ["--filter", "postpone_chunks.py"]
---
Here is a plot.
```{r}
plot(iris)
```
Here is a table.
```{r}
table(iris$Species)
```
And here are the code chunks used to make them:
lastchunk
There is probably a better way to write this in haskell, where you won't need the placeholder. One could also customize the way the code chunks are returned at the end to add a title before each one for instance.