I love using Quarto for slides, reports and papers. However there are some small problems that can be sometimes frustrating.
Show source code of a function
Imagine to have a project folder with several scripts and files. You are preparing a presentation or a report and you are using some custom R functions through the project. Usually you have an R/ folder with one or more *.R files. Then you use source("R/*.R") to load all the custom functions. Actually, if you organise the folder as an R package you can create a more stable and versatile project using devtools::load_all(), but this is another story.
Let’s assume you wrote a custom function within R/utils.R:
myfun <-function(x){ ...}
Then you are writing a report in Quarto and not only you want to use myfun but you want to show the source code on the rendered document. For example you can simply copy and paste the function in a chunk with #| eval: false or with a code-block in plain markdown (no {r}):
```r
myfun <- function(x){
...
}
```
However, functions are usually adjusted, improved or corrected and for this reason this system is not scalable and efficient.
In my filor package I have now two functions to solve this problem: - filor::get_funs() - filor::print_fun()
filor::get_funs() takes one or more path to *.R files and read all the functions as text. The output is a named list with the functions names and the source code as character. Then filor::print_fun() takes one or more functions (imported with filor::get_funs()) printing a nice formatted code. This is exactly the same as creating a plain markdown code block but dynamically importing and printing functions from source scripts. Any change in the source scripts will be reflected in the output. I’ve found these two functions really useful when writing tutorial papers that are full of custom functions that you need to show and explain.
Ideally at the beginning of a Quarto document you can include a code chunk as:
```{r}library(filor)funs <- filor::get_funs("R/utils.R") # use the correct path```
Then when you need to show the function:
```{r}#| output: asisfilor::print_fun(funs$myfun) # myfun is the function name```
Remember to use the #| output: asis option to display the function as a code block.
Filtering output lines
Another common problem in my Quarto documents, especially Revealjs slides, is about output that are too verbose or crowded. For example, let’s imagine to show the summary of a model fitted with lme4 that contains a lot of information. However we are interested in showing only the fixed-effects section or the residuals section. I’ve searched (not really extensively) for a native solution but I ended up writing (with a little help of GPT) a really nice solution.
In my filor package there is a filor::filter_output() function that takes any (textual) output from a function call and return a selection of the initial output. Let’s make an example:
fit <-lm(Sepal.Length ~ Species, data = iris)summary(fit)
Call:
lm(formula = Sepal.Length ~ Species, data = iris)
Residuals:
Min 1Q Median 3Q Max
-1.6880 -0.3285 -0.0060 0.3120 1.3120
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.0060 0.0728 68.762 < 2e-16 ***
Speciesversicolor 0.9300 0.1030 9.033 8.77e-16 ***
Speciesvirginica 1.5820 0.1030 15.366 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.5148 on 147 degrees of freedom
Multiple R-squared: 0.6187, Adjusted R-squared: 0.6135
F-statistic: 119.3 on 2 and 147 DF, p-value: < 2.2e-16
This output contains a lot of information, but maybe I don’t care about Residuals or the last part of the summary. I can use the function to filter the rows to display:
The lines are simply the line numbers of the output. For a more flexible approach you can use regular expressions in the form start|end. For example ^Coefficients|^Signif means to keep the lines where a line start with “Coefficients” up to a line starting with “Signif”.
The only problem is that you need to include the previous chunk in your slide and can be really confusing. Ideally you want to specify the lines elsewhere and leave the chunk clean only using summary(fit). For this reason I implemented also a knitr output hook. Basically, at the beginning of your Quarto document put a chunk with filor::set_filter_output(). Then you can simply include lines as a code chunk option in the same way as used within the function.