bookdown icon indicating copy to clipboard operation
bookdown copied to clipboard

pass on DT::datatable(caption =) argument, label datatables as tables

Open maxheld83 opened this issue 7 years ago • 12 comments

I'm relying a lot on DT::datatable() tables, rather than knitr::kable() static ones.

Because DT::datatable() is an htmlwidget, I seem to be able to set a reference-able, numbered caption only by relying on the knitr chunk option fig.cap =. (I hope I got this right). This makes sense for most of the htmlwidgets, many of which are plots, but, I'd say, not for DT::datatable(), which is actually a table.

Referencing/captioning it as a figure might be confusing for users.

I've tried several approaches to get a DT::datatable() to be properly labeled as a table in bookdown::gitbook(), but without success.

library(DT)
DT::datatable(head(iris), caption = "Table: This is the caption from inside DT")
DT::datatable(head(iris), caption = "(\\#tab:dt-repro) Table: This is the caption from inside DT")
knitr::kable(head(iris), caption = "This is the caption from inside kable")

yield, respectively,

captions

I think it would be nice if I the caption set inside DT::datatable() could be passed on to bookdown() in the appropriate way.

Alternatively, and to remain open to more custom tables, I was wondering whether a chunk option tab.cap= inside knitr might make sense, to be treated analogously to fig.cap = .

Ps.: This might seem like a somewhat trivial issue (whether an actual table is called a figure), but this gets thornier in use cases where people use DT::datatable() for HTML-type outputs, and knitr::kable() for others. In that (my) scenario, the whole numbering and referencing diverges between the different outputs.

maxheld83 avatar Jan 23 '17 17:01 maxheld83

I see your point, but I'm afraid I'm not going to deal with this special case. Calling a table a figure is probably not the end of the world (nobody has complained so far that Figure 2.5 is not a figure at https://bookdown.org/yihui/bookdown/html-widgets.html). On the other hand, in non-HTML output, the DT widget will be a screenshot, which is probably qualified as a "figure".

In short, I tend not to make exceptions for DT widgets, but if this issue makes you sleepless at night, I'll be happy to reconsider it when I have time. Thanks!

yihui avatar Jan 25 '17 05:01 yihui

I agree that having a separate table numbering system for DT tables would be very helpful. In fact, in most of the articles/reports I write, we use separate numbering for Figures and Tables, and therefore using the Figure labelling for tables is not really an option. If you have any other advice, or work-arounds it would be really helpful.

lmcgrath82 avatar May 18 '17 14:05 lmcgrath82

I'll reconsider this issue, but probably not very soon. Thanks!

yihui avatar May 19 '17 06:05 yihui

Thanks for reopening this issue. I think it is an important feature for a robust bookdown. I'm generating a government report using the DT package for dynamic tables. While I understand the argument for calling it a figure in the context of a screen capture for LaTeX, this mis-labeling creates confusion for readers especially if DT and kable tables are intermixed (since the numbering is incremented as if it is a figure). Also, a DT table, labeled as a figure, is likely to raise the ire of communications folks in government that review such things but don't understand the reason behind it being labeled as a figure.

millerjef avatar Feb 07 '18 17:02 millerjef

I propose a more general approach. Why not label and increment counters based on the html <div class = "table"> and/or <p class="caption"> (\#tab:myDT)My labeled DT</p>? This could set up a new counter for any arbitrary class.

I'm more of a scientist than a coder but I'm hoping my explorations helps someone come up with a nifty, efficient solution.

I explored a bunch of things to try to find a work around to get a DT into a table environment/counter. I used the bookdown-demo and edited the 01-intro.Rmd file as my MRE.

By setting keep_md: yes in the _output.yml file and inspecting the compiled .md, I note that:

```{r myDT-fig, fig.cap = "my super duper caption", echo = FALSE, message=FALSE, warning=FALSE}
library(DT)
datatable(head(iris))
```

Produces a <div class="figure"> chunk with the DT widget followed by:

<p class="caption">(\#fig:myDT-fig)my super duper caption</p>
</div>

I pursued this, including:

  1. Setting chunk hooks to prepend the table reference anchor; and
  2. Using htmltools::div and htmltools::p and htmltools::HTML to mimic the .md output generated above.

Using the above techniques (especially htmltools), I can get output that looks very close to the way fig.cap and DT get handled:

```{r myDThtmltools}
library(DT)
library(htmltools)
div(
    class = "table", 
    p(class = "caption", "(\\#tab:myDThtmltools)my caption created using htmltools"), 
    datatable(head(iris))
)
```

The output (snipped) starts as follows:

<div class="table">
<p class="caption">(\#tab:myDTdiv)my caption created using htmltools</p>

<div id="htmlwidget-365bb828ea197c7c2c1f" 
style="width:960px;height:500px;" 
class="datatables html-widget">
</div>

The DT widget renders with this at the top: (\#tab:myDThtmltools)my caption created using htmltools

I'm not sure why this gets parsed differently than a chunk processed with fig.cap. Maybe an easy solution?

millerjef avatar Feb 08 '18 01:02 millerjef

I have found the following workaround for html from https://github.com/rstudio/bookdown/issues/372 After the table produced with DT

library(DT)
datatable(head(iris))

I insert html tag

cat("<table>",paste0("<caption>", "(#tab:mytab)", "caption", " some texte", "</caption>"),"</table>", sep ="\n")

Tab. \@ref(tab:mytab) which gives a desired output capture d ecran 2018-05-20 a 20 14 44

For latex output, I use knitr tables

UrszulaCzerwinska avatar May 20 '18 18:05 UrszulaCzerwinska

I see 4 people posted 👍 ...so the directions are pretty clear...but I'm still a bit confused. If the R markdown looks like this:

---
title: "Untitled"
site: bookdown::bookdown_site
output: bookdown::gitbook
documentclass: book
---

```{r myDThtmltools}
library(DT)
library(htmltools)
div(
    class = "table", 
    p(class = "caption", "(\\#tab:myDThtmltools)my caption created using htmltools"), 
    datatable(head(iris))
)
```
Tab. \@ref(tab:myDThtmltools)

and then I run:

render_book(input = "test.Rmd")

What would I change to "insert html tag" as described above?

ldecicco-USGS avatar Dec 04 '18 16:12 ldecicco-USGS

Nevermind - I figured it out 1 minute after posting, I think the solution is this:

---
title: "Untitled"
site: bookdown::bookdown_site
output: bookdown::gitbook
documentclass: book
---

```{r myDThtmltools, results="asis", echo=FALSE}
library(DT)

datatable(head(iris))
    
cat("<table>",paste0("<caption>", "(#tab:myDThtmltools)", "caption", "Here's my caption", "</caption>"),"</table>", sep ="\n")
```


Tab. \@ref(tab:myDThtmltools)

ldecicco-USGS avatar Dec 04 '18 16:12 ldecicco-USGS

A small note: If your code chunk name has an underscore, the caption label fails. I have no idea why, but I guess that must mean something else in html.

markbneal avatar Mar 10 '20 03:03 markbneal

A small note: If your code chunk name has an underscore, the caption label fails. I have no idea why, but I guess that must mean something else in html.

About this, you can't use _ in chunk name when using referencing mechanism in bookdown. As documented in https://bookdown.org/yihui/rmarkdown/r-code.html we advice to not use underscore

I strongly recommend that you only use alphanumeric characters (a-z, A-Z and 0-9) and dashes (-) in labels, because they are not special characters and will surely work for all output formats. Other characters, spaces and underscores in particular, may cause trouble in certain packages, such as bookdown.

cderv avatar Mar 18 '21 13:03 cderv

I have found the following workaround for html from #372 After the table produced with DT

library(DT)
datatable(head(iris))

I insert html tag

cat("<table>",paste0("<caption>", "(#tab:mytab)", "caption", " some texte", "</caption>"),"</table>", sep ="\n")

Tab. \@ref(tab:mytab) which gives a desired output capture d ecran 2018-05-20 a 20 14 44

For latex output, I use knitr tables

Thanks for the solution! I'm trying this approach, but my caption is being wrapped as if it's being resized to fit a narrow column (I guess it's because it's in a <table> environment. image

Any idea how I can make it fill the entire width of the table that follows?

Thanks, Ido

IdoBar avatar Dec 04 '21 18:12 IdoBar

I managed to fix this by adding a width argument to the table tag <table width=100%> image

IdoBar avatar Dec 04 '21 18:12 IdoBar