quarto - reactable output not shown if followed by other output - r

I have a function which produces multiple tables, e.g. one a reactable, the other the simple printout of a dataframe.
When using the function in a quarto document and rendering it, the output of the reactable is omitted unless it comes last in the function.
Any idea what's going on? I assume it's related to the issue dealt with here, but I don't see how to overcome it.
Many thanks.
Below the code which should reproduce the issue in a qmd document.
---
title: "Untitled"
format: html
---
```{r}
#| echo: true
#| warning: false
library(tidyverse)
library(reactable)
```
Reactable first; not shown in output
```{r}
fn_cars <- function(my_data) {
my_data[1:5,] %>% reactable()
print(my_data[1:5,])
}
```
```{r}
fn_cars(my_data=mtcars)
```
Reactable last, shows in output.
```{r}
fn_cars <- function(my_data) {
print(my_data[1:5,])
my_data[1:5,] %>% reactable()
}
```
```{r}
fn_cars(my_data=mtcars)
```

The problem you are facing is not actually quarto or reactable specific. Its actually how R function works. By default, an R function returns the value of the last expression evaluated.
So in your example, the first function is printing the my_data, since the print was the last expression and returning the my_data invisibly and so You are getting only the printed data, not the reactable. But the second function is printing the my_data and returning the reactable output and that's why you are getting both of them in the output in the second case.
With this fact in mind, either
fn_cars <- function(my_data) {
table <- my_data[1:5, ] %>% reactable()
print(my_data[1:5, ])
table
}
fn_cars(my_data=mtcars)
or
fn_cars <- function(my_data) {
print(my_data[1:5, ])
table <- my_data[1:5, ] %>% reactable()
table
}
fn_cars(my_data=mtcars)
will work as intended.

Related

When I knit a flextable to html there is no output with the table

The table prints nicely in markdown but is not present in the knitted html file. I noticed that it is classified as a list but don't know how to change it to an acceptable file type. The knitted output is not formatted as a table. I appreciate the help.
library("crosstable") #important package crosstable() function
library('dplyr')
library("flextable")
tbl1 = crosstable(mtcars2, c(1), by = 2) %>%
as_flextable(keep_id=FALSE)
print(tbl1)
According to ?print.flextable
Note also that a print method is used when flextable are used within R markdown documents. See knit_print.flextable().
Therefore, if we want to print in Rmarkdown, either use knitr::knit_print or remove the print as the ?knit_print.flextable documentation shows
You should not call this method directly. This function is used by the knitr package to automatically display a flextable in an "R Markdown" document from a chunk.
---
title: "Testing"
author: "akrun"
date: "09/12/2021"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r, echo = FALSE}
suppressPackageStartupMessages(library("crosstable")) #important package crosstable() function
suppressPackageStartupMessages(library('dplyr'))
suppressPackageStartupMessages(library("flextable"))
tbl1 = crosstable(mtcars2, c(1), by = 2) %>%
as_flextable(keep_id=FALSE)
# either use knit_print or remove the print wrapper
#knitr::knit_print(tbl1)
tbl1
```
-output

Convert list of different length into data table for markdown for html format

This is what Im doing to generate a markdown so that all the things should be in one place.
How can i put these output into a datatable form which are more readable and easier to search.The list which is made are of different length. Each list has a series of table under it.
If there a way to convert these differing length list to data table format that would be really helpful
The table looks like this
## Prepare for analyses
```{r,warning=FALSE,message=FALSE}
set.seed(1234)
library(europepmc)
library(tidypmc)
library(tidyverse)
#library(dplyr)
```
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
##Cytarabine cytogenetically normal aml adult clinical trial Randomized Controlled Trial. 828 records found, showing 10
```{r,include=FALSE}
b <-epmc_search(query = 'cytarabine cytogenetically normal aml adult clinical trial Randomized Controlled Trial OPEN_ACCESS:Y',limit = 10)
pmcids <- b$pmcid[b$isOpenAccess=="Y"]
docs <- map(pmcids, epmc_ftxt)
my_tables <- map(docs, pmc_table)
```
```{r}
names(my_tables) <- pmcids
```
The code chunk input and output is then displayed as follows:
```{r basicconsole}
source("flat.R")
L1 <- flattenlist(my_tables)
l.f <- Filter(function(a) any(!is.na(a)), L1)
l.f
#tibble:::print.tbl_df(head(df))
#n <- paste0("Valporic_", names(l.f), ".txt")
for (i in 1:length(l.f)) {
write.table(l.f[i], sep = "\t",row.names = FALSE,col.names = TRUE,file=paste0(names(l.f)[i], ".txt"))
}
UPDATE
I have manged to covert those tibble into dataframe
using this solution
##Outout
```{r}
abc <- mapply(cbind, l.f)
abc
But when it is rendered in the markdown the column formatting is gone. Now i have now dataframe inside list.
But still im not sure how to put that into a data table
**UPDATE 2.0 **
The better approach is to read those saved output as list of files into data table and then use it as markdown but so far it is taking only one ID only. My code.
tbl_fread <-
list.files(pattern = "*.txt") %>%
map_df(~fread(.))
knitr::kable(head(tbl_fread), "pipe")
Is it possible to put these files as such.
if a list of file are from one PMCID then those would be all in one column such as if PMCID one has 3 output then all of them should be one the same row. Then the next PMCID in the second one etc etc.
UPDATE new
I have managed to align the output into more readable format. But It seems that by default all the files assigned to multiple columns which would be the case given that im reading all the files together since my idea of using the list to data table didn't work.
If i can push or stack each unique PMCID over one another instead of all in one after another that would be. Good
knitr::kable(tbl_fread, align = "lccrr")
This may be something you can adapt for R Markdown. I'm not sure what the rationale is to save and load the tables. Instead, you could obtain the tables and show in html directly.
As you are using HTML, make sure to have results='asis' in your chunk. You can use a for loop and seq_along to show each table. You can include information in your table caption, such as the PMCID as well as table number.
---
title: "test13121"
author: "Ben"
date: "1/31/2021"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Libraries
```{r}
library(tidypmc)
library(tidyverse)
library(europepmc)
library(kableExtra)
```
# Get Articles
```{r, echo = FALSE}
b <-epmc_search(query = 'cytarabine aml OPEN_ACCESS:Y',limit = 6)
pmcids <- b$pmcid[b$isOpenAccess=="Y"]
docs <- map(pmcids, epmc_ftxt)
my_tables <- map(docs, pmc_table)
names(my_tables) <- pmcids
```
# Show Tables
```{r, echo=F, results='asis'}
for (i in seq_along(my_tables)) {
for (j in seq_along(my_tables[[i]])) {
print(kable(x = my_tables[[i]][[j]], caption = paste0(names(my_tables)[i], ": Table ", j)))
}
}
```

Inline referencing of a code chunk in document

Suppose there is a code chunk as follows:
```{r mean diff}
(5-mean(dnorm(40,5,2))/5
```
I would like to be able to reference this code chunk with its label in inline form in a markdown document, so that the reference is replaced by the output of this chunk. Is there a way to do it?
" the difference is `r mean diff` %." ##something like this?
I think the answer to your question is "yes, but it's tricky". By default knitr doesn't save the last value computed in a code chunk. In regular code, the last value calculated is saved in .Last.value, but knitr doesn't simulate this.
However, a simple modification lets you do something very similar:
```{r}
meandiff <- 5-mean(dnorm(40,5,2))/5
meandiff # if you want the chunk to print its value
```
and then in the text, use
" the difference is `r meandiff` %."
If you really want to save the last value, it's possible by setting a "render hook". For example, the code below saves the last value, then calls the old hook:
```{r}
.Last.value <- NULL
old_hook <- knitr::opts_chunk$get("render")
knitr::opts_chunk$set(render = function(x, options, ...) {
.Last.value <<- x
if (!is.null(old_hook))
old_hook(x, options, ...)
else
knitr::knit_print(x, options, ...)
})
```
```{r mean diff}
5-mean(dnorm(40,5,2))/5
```
The value was `r .Last.value`.

R markdown rerun the same section of report with different parameter

I'm familiar with R markdown "parameters".
However, say I want to generate the same report (same chart, same table) but for 5 different regions.
Is there a way to do this elegantly in a loop or lapply or do I need to make several sections. So in pseudo code I want to do something like:
for(i in 1:5):
Bunch of text
table[i]
plot[i]
Instead of
bunch of text
table[1]
plot[1]
bunch of text
table[2]
plot[2]
...
Put another way, I want to functionalize a "section" of the report, and then I can call
for(i in 1:5):
makeReport(i)
And it will go in, put in the text, figures, etc associated with index i.
You have to call print explicitly if inside for loop:
```{r}
for(i in 1:2) {
print(summary(cars[,-i]))
plot(cars[,-i])
}
```
or
```{r}
makeReport <- function(i) {
print(summary(cars[,-i]))
plot(cars[,-i])
}
for(i in 1:2) {
makeReport(i)
}
```
Update
As Stéphane Laurent already demonstrated in Dynamic number of calls to a chunk with knitr
you can define a child .rmd:
test_section.rmd
Header: `r i`-th cars
```{r}
print(summary(cars[,-i]))
plot(cars[,-i])
```
and in the main rmd file concatenate the results:
```{r runall, include=FALSE}
out <- NULL
for (i in 1:2) {
out <- c(out, knitr::knit_child('test_section.rmd'))
}
```
`r paste(out, collapse = '\n')`

Creating summaries at the top of a knitr report that use variables that are defined later

Is there a standard way to include the computed values from variables early on in the written knitr report before those values are computed in the code itself? The purpose is to create an executive summary at the top of the report.
For example, something like this, where variable1 and variable2 are not defined until later:
---
title: "Untitled"
output: html_document
---
# Summary
The values from the analysis are `r variable1` and `r variable2`
## Section 1
In this section we compute some values. We find that the value of variable 1 is `r variable1`
```{r first code block}
variable1 <- cars[4, 2]
```
## Section 2
In this section we compute some more values. In this section we compute some values. We find that the value of variable 2 is `r variable2`
```{r second code block}
variable2 <- cars[5, 2]
```
A simple solution is to simply knit() the document twice from a fresh Rgui session.
The first time through, the inline R code will trigger some complaints about variables that can't be found, but the chunks will be evaluated, and the variables they return will be left in the global workspace. The second time through, the inline R code will find those variables and substitute in their values without complaint:
knit("eg.Rmd")
knit2html("eg.Rmd")
## RStudio users will need to explicitly set knit's environment, like so:
# knit("eg.Rmd", envir=.GlobalEnv)
# knit2html("eg.Rmd", envir=.GlobalEnv)
Note 1: In an earlier version of this answer, I had suggested doing knit(purl("eg.Rmd")); knit2html("eg.Rmd"). This had the (minor) advantage of not running the inline R code the first time through, but has the (potentially major) disadvantage of missing out on knitr caching capabilities.
Note 2 (for Rstudio users): RStudio necessitates an explicit envir=.GlobalEnv because, as documented here, it by default runs knit() in a separate process and environment. It default behavior aims to avoid touching anything in global environment, which means that the first run won't leave the needed variables lying around anywhere that the second run can find them.
Here is another approach, which uses brew + knit. The idea is to let knitr make a first pass on the document, and then running it through brew. You can automate this workflow by introducing the brew step as a document hook that is run after knitr is done with its magic. Note that you will have to use brew markup <%= variable %> to print values in place.
---
title: "Untitled"
output: html_document
---
# Summary
The values from the analysis are <%= variable1 %> and
<%= variable2 %>
## Section 1
In this section we compute some values. We find that the value of variable 1
is <%= variable1 %>
```{r first code block}
variable1 = cars[6, 2]
```
## Section 2
In this section we compute some more values. In this section we compute
some values. We find that the value of variable 2 is <%= variable2 %>
```{r second code block}
variable2 = cars[5, 2]
```
```{r cache = F}
require(knitr)
knit_hooks$set(document = function(x){
x1 = paste(x, collapse = '\n')
paste(capture.output(brew::brew(text = x1)), collapse = '\n')
})
```
This has become pretty easy using the ref.label chunk option. See below:
---
title: Report
output: html_document
---
```{r}
library(pixiedust)
options(pixiedust_print_method = "html")
```
### Executive Summary
```{r exec-summary, echo = FALSE, ref.label = c("model", "table")}
```
Now I can make reference to `fit` here, even though it isn't yet defined in the script. For example, a can get the slope for the `qsec` variable by calling `round(coef(fit)[2], 2)`, which yields 0.93.
Next, I want to show the full table of results. This is stored in the `fittab` object created in the `"table"` chunk.
```{r, echo = FALSE}
fittab
```
### Results
Then I need a chunk named `"model"` in which I define a model of some kind.
```{r model}
fit <- lm(mpg ~ qsec + wt, data = mtcars)
```
And lastly, I create the `"table"` chunk to generate `fittab`.
```{r table}
fittab <-
dust(fit) %>%
medley_model() %>%
medley_bw() %>%
sprinkle(pad = 4,
bg_pattern_by = "rows")
```
I work in knitr, and the following two-pass system works for me. I have two (invisible) code chunks, one at the top and one at the bottom. The one at the bottom saves the values of any variables I need to include in the text before they are actually computed in a file (statedata.R). The top chunk sets the variable values to something that stands out if they haven't been defined yet, and then (if it exists) it grabs the actual values from the stored file.
The script needs to be knit twice, as values will be available only after one pass through. Note that the second chunk erases the saved state file at the end of the second pass, so that any later changes to the script that affect the saved variables will have to be computed anew (so that we don't accidentally report old values from an earlier run of the script).
---
title: "Untitled"
output: html_document
---
```{r, echo=FALSE, results='hide'}
# grab saved computed values from earlier passes
if (!exists("variable1")) {
variable1 <- "UNDEFINED"
variable2 <- "UNDEFINED"
if (file.exists("statedata.R")) {
source("statedata.R")
}
}
# Summary
The values from the analysis are `r variable1` and `r variable2`
## Section 1
In this section we compute some values. We find that the value of variable 1 is `r variable1`
```{r first code block}
variable1 <- cars[4, 2]
```
## Section 2
In this section we compute some more values. In this section we compute some values. We find that the value of variable 2 is `r variable2`
```{r second code block}
variable2 <- cars[5, 2]
```
```{r save variables for summary,echo=FALSE,results='hide'}
if (!file.exists("statedata.R")) {
dump(c("variable1","variable2"), file="statedata.R")
} else {
file.remove("statedata.R")
}
```
Latex macros can solve this problem. See this answer to my related question.
\newcommand\body{
\section{Analysis}
<<>>=
x <- 2
#
Some text here
} % Finishes body
\section*{Executive Summary}
<<>>=
x
#
\body

Resources