yihui / knitr

A general-purpose tool for dynamic report generation in R
https://yihui.org/knitr/
2.39k stars 878 forks source link

Kable table caption as chunk option with tab.cap? #1679

Closed ulyngs closed 11 months ago

ulyngs commented 5 years ago

This might be due to 'complicated reasons', but it would be fantastic if the syntax for providing captions to figures and tables was similar.

That is, rather than provide a table caption with

```{r}
knitr::kable(head(cars), caption = "A kable table")

one could provide the caption with
knitr::kable(head(cars))


As I was putting together teaching materials for an R Markdown workshop I realised that it seemed strange that `fig.cap` didn't have a `tab.cap` equivalent.
yihui commented 5 years ago

Haha, there are no "complicated reasons". I have actually thought about this before. The only complication is when there are multiple kable()s in a single R code chunk, in which case tab.cap should be a vector, and it would be a little tricky to assign each caption to each kable().

ulyngs commented 5 years ago

Ah I see - I've never ever had a need for multiple kable() calls in a single code chunk, so perhaps in that (perhaps rare) use case it could simply throw an error telling the user that if they wish to create multiple tables simultaneously, then they must assign captions in the individual kable function calls?

mpaolo commented 4 years ago

Hi,

looks the same for plots/figures though - if I put a couple of plots in same chunk the fig.cap disappears. So we'd have a consistent rule for both tab.cap and fig.cap: 1 tab/plot/figure per chunk if you want the chunk's caption, else manage them otherwise. Since kable()'s format=markdown loses the caption=* option, such tab.cap at chunk level would be a solution also for that.

Ah, BTW ... is there a reason why kable()'s caption is not latex-scaped like the actual table data? I often mention var names in the caption like they're in row/col names, but knitting chokes when a var name has e.g. a '_' in it and is also in the caption (and I forget to pre-escape the cap text).

thx

ChrisWaloszek commented 4 years ago

I second @mpaolo's comment! tab.cap='(ref:XXX)', tab.scap='(ref:YYY)'} working just as fig.cap='(ref:XXX)', fig.scap='(ref:YYY)'} would be very helpful. This approach of adding captions would also come useful to other table generating packages like huxtable for example. The same holds for labels and referencing them. It would be nice to have things streamlined across tables and figures simply through optional options added to a chunk. To tackle the issue of multiple figures generated in a chunk: just split it into several, labeled chunks (and drop the code into a separate R/Rmd file which is sourced in each chunk in the main file).

dmgt commented 4 years ago

While understanding this may not be a priority, I would like to respectfully add one more voice that an option to directly caption tables in chunk headers would be useful.

One use case I have encountered (in a team migrating to RMarkdown and LaTeX with many Word/Excel users), is that sometimes it'd be helpful to be able to embed an image of an existing table and label it as a table instead of a figure, which currently doesn't seem to be straightforward (workaround option here).

While I know it sounds less reproducible, it's been a common ask in our workflow, eg to embed an existing table with complex formatting as an image as part of the introduction or methods section of a project. Thank you!

ulyngs commented 4 years ago

This particular use case I think already has a straightforward solution with the chunk option fig.env:

```{r, fig.env='table', fig.cap="Table included as image"}
knitr::include_graphics("image-of-a-table.png")
chrisothal commented 4 years ago

I would also like to request this feature for the use case when printing via kable() is not used. The workaround hack I use is to include the table caption directly underneath the chunk and let pandoc-crossref interpret that as the caption, but it would be nice to have a solution that is self-contained within the same chunk:

```{r self-contained-table-label}
readxl::read_excel("path/to/excel.xlsx")

Table: Table caption here {#tbl:free-hanging-table-label}

Referencing @tbl:self-contained-table-label within it's own code chunk but the reference is undefined.

francisbarton commented 2 years ago

I think it's worth noting that David Gohel in his {flextable} package documentation suggests using a tab.cap chunk option as one way to generate table captions. I thought "oh, neat, I didn't realise that was an option in knitr" - and then I tried to look it up in the knitr/rmarkdown documentation and couldn't find it referenced anywhere (except here).

cderv commented 2 years ago

Thanks @francisbarton. For reference, these options are custom options from officer 📦 https://github.com/davidgohel/officer/blob/0591d88127d4fa5aa6006eabe55329a1955b7bd0/R/knitr_utils.R#L127

They do not exist in knitr but this feature request would surely port them here.

yihui commented 11 months ago

The chunk option tab.cap is supported now, and kable() will first try to retrieve the caption from this option. Only one kable() per code chunk, and tab.cap should be of length 1.

To test it, you can install the development version via

remotes::install_github('yihui/knitr')

Thanks! And apologies for taking so long to make this simple change (due to my overthinking at that time and then poor memory later).

github-actions[bot] commented 5 months ago

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue by following the issue guide (https://yihui.org/issue/), and link to this old issue if necessary.