I'm looking for a way to adjust functions which usually show html tables in the viewer or browser in a way that they automatically insert the html in knitr documents like rnotebooks when called.
Specifically I want to change the way functions in the package sjPlot behave. At the moment they return an object with a $knitr attribute that has to be inserted manually and then produce an html table in the viewer:
`r sjt.frq(efc$e42dep, no.output=TRUE)$knitr`
One of these functions is sjt.frq. Is there a way to do this?
From knit_print:
library(knitr)
a = 42
class(a) = "my_class"
knit_print.my_class = function(x,...){
res = paste("{{", x,"}}")
asis_output(res)
}
a
It works when I knit document but doesn't work with RNotebooks and doesn't work with sjt.frq. However with RNotebook works the following statement:
library(sjPlot)
library(sjmisc)
library(knitr)
data(efc)
asis_output(sjt.frq(efc$e42dep, no.output=TRUE)$knitr)
Related
I want to create a footer within the float for a figure created with ggplot2 in an rmarkdown document that is generating a .pdf file via LaTeX.
My question: Is there a way within rmarkdown/knitr to add more LaTeX commands within the figure environment?
Specifically, I'd like to find a way to insert custom LaTeX using either the floatrow or caption* macro as described in https://tex.stackexchange.com/questions/56529/note-below-figure within the figure environment.
When I looked at the chunk options (https://yihui.org/knitr/options/#plots), something like out.extra seems close to what I want, but that is used as an extra option to \includegraphics while I want access to put extra LaTeX within the figure environment, outside of any other LaTeX command.
The solution to your question is perhaps quite similar to this one. However, I believe yours is a bit more general, so I'll try to be a bit more general as well...
As far as I know, there's no simple solution to add extra LaTeX code within the figure environment. What you can do is update the knit (or output) hook (i.e. the LaTeX code output generated by the figure chunk).
The source code for the LaTeX figure output hook can be found here (hook_plot_tex). The output generated can be found starting at line 159. Here we can see how the output is structured and we're able to modify it before it reaches the latex engine.
However, we only want to modify it for relevant figure chunks, not all. This is where Martin Schmelzer's answer comes in handy. We can create a new chunk option which allows for control over when it is activated. As an example enabling the use of caption* and floatrow we can define the following knit hook
defOut <- knitr::knit_hooks$get("plot")
knitr::knit_hooks$set(plot = function(x, options) {
#reuse the default knit_hook which will be updated further down
x <- defOut(x, options)
#Make sure the modifications only take place when we enable the customplot option
if(!is.null(options$customplot)) {
x <- gsub("caption", "caption*", x) #(1)
inter <- sprintf("\\floatfoot{%s}\\end{figure}", options$customplot[1]) #(2)
x <- gsub("\\end{figure}", inter, x, fixed=T) #(3)
}
return(x)
})
What we're doing here is (1) replacing the \caption command with \caption*, (2) defining the custom floatfoot text input, (3) replacing \end{figure} with \floatfoot{custom text here}\end{figure} such that floatfoot is inside the figure environment.
As you can probably tell, sky's the limit for what you can add/replace in the figure environment. Just make sure it is added inside the environment and is in the apropriate location. See the example below how the chunk option is used to enable floatfoot and caption*. (You can also split the customplot option into e.g. starcaption and floatfoot by simply dividing up the !is.null(options$customplot) condition. This should allow for better control)
Working example:
---
header-includes:
- \usepackage[capposition=top]{floatrow}
- \usepackage{caption}
output: pdf_document
---
```{r, echo = F}
library(ggplot2)
defOut <- knitr::knit_hooks$get("plot")
knitr::knit_hooks$set(plot = function(x, options) {
x <- defOut(x, options)
if(!is.null(options$customplot)) {
x <- gsub("caption", "caption*", x)
inter <- sprintf("\\floatfoot{%s}\\end{figure}", options$customplot[1])
x <- gsub("\\end{figure}", inter, x, fixed=T)
}
return(x)
})
```
```{r echo = F, fig.cap = "Custom LaTeX hook chunk figure", fig.align="center", customplot = list("This is float text using floatfoot and floatrow")}
ggplot(data = iris, aes(x=Sepal.Length, y=Sepal.Width))+
geom_point()
```
PS
The example above requires the fig.align option to be enabled. Should be fairly easy to fix, but I didn't have the time to look into it.
#henrik_ibsen gave the answer that got me here. I made some modifications to the code that I ended up using to make it work a bit more simply:
hook_plot_tex_footer <- function(x, options) {
x_out <- knitr:::hook_plot_tex(x, options)
if(!is.null(options$fig.footer)) {
inter <- sprintf("\\floatfoot{%s}\n\\end{figure}", options$fig.footer[1])
x_out <- gsub(x=x_out, pattern="\n\\end{figure}", replacement=inter, fixed=TRUE)
}
x_out
}
knitr::knit_hooks$set(plot=hook_plot_tex_footer)
Overall, this does the same thing. But, it uses knitr:::hook_plot_tex() instead of defOut() so that if rerun in the same session, it will still work. And, since it's going into a \floatfoot specifically, I named the option fig.footer. But, those changes are minor and the credit for the answer definitely goes to #henrik_ibsen.
How do I go about removing the output shown in the picture below after I use read_excel to import the data in r markdown. Basically I don't want there to be any output after this function. Please see attached image.
bdims <- read_excel("bdims.xlsx")
head(bdims)
You can set results = 'hide'. So if eg. for standard rmarkdown. This will stop the output from showing. Read on the cheat sheet how to use other settings such as echo and eval
{results = 'hide'}
bdims <- read_excel("bdims.xlsx")
or with roxygen document for rendering rmarkdown,
#+ results = 'hide'
bdims <- read_excel("bdims.xlsx")
I am using blogdown to to create a blogpost that has a series of tables. Creating a single table using the kable function works fine. If you do
blogdown::new_site()
blogdown::new_post("test", ext = ".rmd")
A new rmd file will be created within the content/post directory of the project. If you open that file and create a single table by doing
```{r test1}
library(knitr)
library(magrittr)
library(shiny)
data.frame(a= c(1,2,3)) %>% kable(caption = 'test',format = 'html')
```
A correctly formatted table will be generated. The caption will read "
Table 1: test" If you look at the code of the generated site, the caption will look like this.
<caption>
<span id="tab:test1">Table 1: </span>test
</caption>
Ideally I don't have any desire to label the table as Table 1 in the first place but that is another question. If formatting of captions by kable can be disabled entirely, I'd also be happy.
However if I use lapply to generate 2 tables instead
```{r test2}
lapply(1:2,function(x){
data.frame(a= c(1,2,3)) %>% kable(caption = 'test2',format = 'html') %>% HTML()
}) -> tables
tables[[1]]
tables[[2]]
```
The captions will have the prefix \#tab:test2. If you look at the caption of these tables, you'll see
<caption>(\#tab:test2)test2</caption>
The question is, why kable behaves differently when its called from a lapply compared to its behaviour outside? Note that both of these behaviours are different that its behaviour when simply knitting the file as an html_document.
I did some digging into the kable's code and found that the caption link is created by the knitr:::create_label function. Looking into this function, I saw the part that is responsible for the wrong behaviour seen with the multiple tables.
if (isTRUE(opts_knit$get("bookdown.internal.label"))) {
lab1 = "(\\#"
lab2 = ")"
}
I could not find the code, responsible for the "correct" behaviour with the single table but it seems like knitr internal options are responsible.
Ultimately the behaviour that I want is simply
<caption>test</caption>
which is the behaviour when simply knitting an html document. But I am yet to find a way to set the relevant knitr options and why are they different within the same document.
Edit: Further examination suggests that the issue isn't lapply specific. It can be replicated using a for loop or even { by itself. A complete post with all the problematic examples can be acquired from this issue on knitr's github page. This github repo includes the basic blogdown site that replicates the issue
Turns out the responsible party is not the lapply call but the HTML call at the end. It seems like the regular process by knitr in blogdown and bookdown is to have a temporary marker for the table references in the form of (\#tab:label) and replace it with the appropriate syntax later in the processing.
I was using the HTML call to be able to use the tags object in shiny/htmltools to bind the tables together. This approach seems to make the process of replacing the temporary marker impossible for reasons outside my understanding. For my own purposes I was able to remove the temporary marker all together to get rid of both malformed captions and the working-as-intended table numbers by doing
remove_table_numbers = function(table){
old_attributes = attributes(table)
table %<>% as.character() %>% gsub("\\(\\\\#tab:.*?\\)","",.)
attributes(table) = old_attributes
return(table)
}
data.frame(a= c(1,2,3)) %>% kable(caption = 'test',format = 'html') %>% remove_table_numbers
This question still would benefit from a proper explanation of the reference link placement process and if its possible to apply it to tables in HTML calls as well. But for know this solves my issue. I'll gladly switch the accepted answer if a more complete explanation appears
I have an RMarkdown document where I use data.tree and DiagrammeR to generate models. I then display these using a set-up similar to the one used in How to include DiagrammeR/mermaid flowchart in a Rmarkdown file
For example:
```{r fig.cap="Structureel model bij enkelvoudige regressie.", fig.with=4, fig.height=1}
drawStructuralModel <- function(covariates, criterion) {
### Create tree
res <- Node$new(criterion);
for (covariate in covariates) {
res$AddChild(covariate);
}
### Set display settings
SetEdgeStyle(res, dir='back');
res <- ToDiagrammeRGraph(res, direction = "descend");
res <- add_global_graph_attrs(res, "layout", "dot", "graph");
res <- add_global_graph_attrs(res, "rankdir", "RL", "graph");
### Draw and return tree
render_graph(res);
}
drawStructuralModel("X", "Y");
```
So far so good. The caption text is added, which is what you'd expect.
Except :-)
Above, in the 'setup' knitr chunk, I used setFigCapNumbering from userfriendlyscience (see https://github.com/Matherion/userfriendlyscience/blob/master/R/setFigCapNumbering.R). This function uses knit_hooks$set to set a hook for plots, so that the captions are automatically numbered.
But this numbering isn't applied to the DiagrammeR output.
I guess that makes sense, since it's not actually a plot, rather an HTML widget or some SVG or so. I would still like it to be numbered as a figure, though.
But how do I find out which hook knitr invokes when DiagrammeR output is generated?
I could always resort to using the more generic 'automatic caption' function setCaptionNumbering (https://github.com/Matherion/userfriendlyscience/blob/master/R/setCaptionNumbering.R), and tell it to use the same counter option as the figure caption thingy uses. That would sidestep the issue, but I'd prefer to modify the appropriate knitr hook.
And since this problem (figuring out which hook knitr uses for output produced by a given function) probably occurs more often, I thought it would be worth opening an SA question.
Does anybody know how you can find this out?
knitr calls knit_print on the output produced by a given chunk. This then calls the appropriate method based on the class of the output. You can find out what methods are available by running methods("knit_print"), then see if any of those match the class of the output from DiagrammeR.
Looking at your example, I'm guessing the class of your output is "DiagrammeR" "htmlwidget", so knitr is calling knit_print.htmlwidget.
Digging into that source code, it calls htmltools::knit_print.html, which wraps the tags and then outputs asis. So to answer your question, it uses the default hooks for asis output in whatever output format you're using.
Is it possible to include R documentation in knitr output? When using stock datasets, it would be nice to just include the builtin documentation without having to copy and paste it in. The problem appears to be that ? works by side effect and so there is no "result" in a meaningful sense. For example,
```{r}
?mtcars
```
has no output that is trapped by knitr.
Using help(...,help_type) instead of ? doesn't help either. I've tried:
```{r, results='markup'}
help(mtcars, help_type="text")
```
and
```{r, results='asis'}
help(mtcars, type="html")
```
with the same result. (In the latter case, knitr did trap the output ## starting httpd help server ... done, which is basically just a message about the side effect.)
In other words, is there a way to extract R help in plain text or HTML?
To answer your specific question, "Is there a way to extract R help in plain text or HTML?", the answer would be to use a combination of Rd2HTML or Rd2txt from the "tools" package, with a little bit of help from .getHelpFile from "utils".
For HTML:
tools:::Rd2HTML(utils:::.getHelpFile(help(mtcars)))
For txt:
tools:::Rd2txt(utils:::.getHelpFile(help(mtcars)))
By the sounds of it, though, you should be able to use the function I've linked to in the comment above. For instance, to include the text from the "Description" section of the "mtcars" help page, you would use something along the lines of:
```{r, echo=FALSE, results='asis'}
cat(helpExtract(mtcars, section = "Desc", type = "m_text"))
```
I think you can get what you want by hacking the pager option as follows:
pfun <- function(files, header, title, delete.file) {
all.str <- do.call("c",lapply(files,readLines))
cat(all.str,sep="\n")
}
orig_pager <- options(pager=pfun)
help("mtcars")
options(orig_pager)
(you can return the character vector from the function instead of cat()ing it if you prefer).
Use printr, e.g.
library(printr)
help(mtcars)
detach('package:printr', unload = TRUE)