Interactive data frames in rmarkdown::render() like RStudio's Preview (or, printing in Rmd)

tl;dr

  • Printed data frames in an HTML notebook created with RStudio's Preview button has pretty, interactive data frames
  • Printed data frames in an HTML notebook created with rmarkdown::render() does not
  • Non-printed data frames look the same in both (i.e. df as opposed to print(df)

reprex

Whitespace added so the ``` ticks could be displayed

  1. Create the following RMD file, save two copies.
    ---
    title: "R Notebook"
    output: html_notebook
    ---

    ```{r}
    df <- data.frame(One = 1:26, Two = letters)
    df
    ```

    ```{r}
    print(df)
    ```
  1. Open one copy in RStudio. Run it, and click Preview. Open the resulting file in browser.
  2. Render the other copy with `rmarkdown::render("second-copy.Rmd", "html_notebook"). Open resulting file in browser.
  3. Compare the results.
  4. See that while the first tibble looks the same in both HTML documents, the second does not.

In full

When I run a Rmd notebook in RStudio, and then hit Preview, the resulting HTML document printed data frames are interactive (you can click through multiple pages) and pretty:

However, when I render the notebook with rmarkdown::render(), I can't achieve the same result. Instead, data frames are presented in plaintext and without interactivity:

To render I have used

rmarkdown::render("file.Rmd",  output_file = "file.nb.html")
rmarkdown::render("file.Rmd", "html_notebook")
rmarkdown::render("file.Rmd",  output_file = "file.html")
rmarkdown::render("file.Rmd", "html_document")

I have found that the inconsistency is only with printed data frames (e.g. print(df)). I've previously chosen to print all the data frames because a) I understand that is good practice and b), more crucially, when I don't, some of the desired data frames aren't printed.

knitr is using custom print method to do its magic. This means when a data.frame object is a result of a chunk knit_print.data.frame will be called.

The interactive table you see is a [paged_table()](https://pkgs.rstudio.com/rmarkdown/reference/paged_table.html) and the function is used by default on data.frame through the df_print argument (3.1 HTML document | R Markdown: The Definitive Guide)

By using print(df) you are preventing the knit_print() to be used, and thus you don't get all the processing that knitr would do usually.

Why do you think this is good practice to print the object ? In R Markdown document, this is definitely not a good practice.

  1. Open one copy in RStudio. Run it, and click Preview. Open the resulting file in browser.

This is indeed inconsistent but this is a IDE only feature. I believe RStudio IDE is overriding the print.data.frame with the function used for paged tables. This is for better experience as notebook mode in the IDE. As html_notebook is a special format tied to this, anything run interactively is cached and then reinject in the .nb.html when doing Preview . When you render, it will execute all the chunk leaving out IDE only feature.

You can recreate it by overriding print.data.frame method if you really need to

---
title: "R Notebook"
output: html_notebook
---

```{r}
print.data.frame <- rmarkdown:::print.paged_df
```


```{r}
df <- data.frame(One = 1:26, Two = letters)
df
```

```{r}
print(df)
```

Though I would not do print(df) in the first place. If you print explicitely all the object, you will get some other side effect with other objects in R.

Thank you for this helpful explanation. This brings a lot of clarity.

I normally do not print() within a notebook, but I resorted to doing so because a number of objects that I was implicitly printing (that is, calling df rather than print(df) were not getting printed at all. Maybe I was cramming too much into a single chunk.

There actually is good reason for adding the print() as opposed to implicitly printing, whether or not print() is the best solution or not.

Within an if-block, only the final object is printed in an Rmd, as if is actually a function.

More is written here.

Yes but I believe you can also use knitr::knit_print() on those.

And the other technics is to store result into an object and then call the object in a later chunk, or use knit_child() or knit_expand()

So yes printing can be useful and required, but there will be side effect and limitations that you need to overcome

This topic was automatically closed 45 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.