How to move the caption of table generated by kable function in Rmarkdown to the bottom? - r-markdown

The following simple code in Rmarkdown will generate a table with a caption on top.
library(dplyr)
df <- iris %>% head()
knitr::kable(df, caption = "Table caption is on the top")
Is there any way to move the table caption generated by kable function to the bottom?

Try the package {xtable} which does put table caption at bottom and then pass the xtable object to kableExtra::xtable2kable to turn the xtable object into a kable object and then you have the caption at the bottom of the table.
```{r message=FALSE}
library(dplyr)
library(xtable)
library(kableExtra)
df <- iris %>% head()
xtable(df, caption = "Table caption is on the top") %>%
xtable2kable()
```
The rendered output looks like
To know more about this caption position issue, follow this issue-thread on Github.

Related

Adding a letter to all table numbers in RMarkdown

I'm using RMarkdown to create Supplementary documents for a paper. These supplements contain many tables. Let's call these documents Supplement A and Supplement B. I want the table numbering to reflect the supplement letter, that is, Table A1 or Table 1A for the first table in Supplement A and so on for all tables.
How can I modify the table numbering to add a letter into the table numbering schema?
Here's an example that will produce a table with normal numbering:
---
title: "Supplement A"
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
library(knitr)
library(kableExtra)
```
```{r cars}
kable(mtcars[1:5, ], booktabs=TRUE, caption="MTCars") %>%
kable_styling(latex_options="hold_position", position="left")
```
An inelegant solution using the captioner package (details provided here: https://datascienceplus.com/r-markdown-how-to-number-and-reference-tables/) can create captions and insert them manually just before the code chunk. Combining this with the Latex package caption makes it possible to remove the automatic table naming and numbering if the caption is generated within the code chunk (How to suppress automatic table name and number in an .Rmd file using xtable or knitr::kable?). I've done this in the YAML with \captionsetup[table]{labelformat=empty}, but it can be done in the document body also. Either way, the caption can then be generated within the code chunk, which was important in my case.
This solution stops bookdown referencing from working (because labelformat cannot be empty), but a workaround for table referencing was provided in the link for using the captioner package (and is included below).
---
title: "Supplement A"
header-includes:
- \usepackage{caption}
\captionsetup[table]{labelformat=empty}
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
library(knitr)
library(kableExtra)
library(captioner)
library(stringr)
```
```{r captions}
# Create the caption(s)
caption <- captioner("Table A", FALSE)
tab_1_cap <- caption("Tab_1", "MTCars")
# Create a function for referring to the tables in text
ref <- function(x) str_extract(x, "[^:]*")
```
The following table is `r ref(tab_1_cap)`.
```{r cars}
kable(mtcars[1:5, ], booktabs=TRUE, caption=tab_1_cap) %>%
kable_styling(latex_options="hold_position", position="left")
```
An alternative solution is avaiable via LaTeX. Add the following somewhere in the body of the document to change the default figure and table names to include the letter.
\def\figurename{Figure A}
\def\tablename{Table A}
To reference a table or figure in text use, e.g., Table A\#ref(tab:label), after defining the table label as normal.
This alone will leave a space in the table/figure caption (e.g., 'Table A 1' instead of 'Table A1'). This can be solved by adding the following to the YAML:
header-includes:
- \usepackage{caption}
- \DeclareCaptionLabelFormat{nospace}{#1#2}
- \captionsetup[figure]{labelformat=nospace}
- \captionsetup[table]{labelformat=nospace}
The \DeclareCaptionLabelFormat creates a function (here labeled nospace), which overrides the default caption label when called. #1 represents the label assigned to refer to tables or figures (e.g., 'Table A') and #2 represents the number of the table or figure. The captionsetup lines change the label format for all tables and figures to the format defined by 'nospace'.
Thus, the code produces, e.g., 'Table A1: Table name' as the caption. If instead you wanted, e.g., 'Table A-1: Table name', the code in \DeclareCaptionLabelFormat should be changed to {#1-#2}.
---
title: "Supplement A"
output: bookdown::pdf_document2
toc: false
header-includes:
- \usepackage{caption}
- \DeclareCaptionLabelFormat{nospace}{#1#2}
- \captionsetup[figure]{labelformat=nospace}
- \captionsetup[table]{labelformat=nospace}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
library(knitr)
library(kableExtra)
library(bookdown)
```
\def\figurename{Figure A}
\def\tablename{Table A}
See Table A\#ref(tab:cars) for something about cars.
(ref:cars) Table caption
```{r cars}
kable(mtcars[1:5, ], booktabs=TRUE, caption="(ref:cars)") %>%
kable_styling(latex_options="hold_position", position="left")
```
Answer inspired by: Figure name in caption using RMarkdown
Caption latex package documentation: https://ctan.org/pkg/caption

kableExtra: set table width on ioslides_presentation

I am using kableExtra on a ioslides_presentation R markdown file.
The table however does not fit the width of the slide:
I am using the following code to generate the table:
library(kable)
library(kableExtra)
data %>%
kable() %>%
kable_styling(c("striped", "hover", "condensed", "responsive"),full_width = FALSE)
I've also tried the argument full_width = TRUE, but was not successful.
How can I force this to happen automatically?
It turns out that it is possible to add a scroll bar to the table.
This can be done using the scroll_box function as follows:
library(kable)
library(kableExtra)
data %>%
kable() %>%
kable_styling(c("striped", "hover", "condensed", "responsive")) %>%
scroll_box(width = "100%")

Selective datatable creation within flexmarkdown

I am trying to build a selector for a datatable object in my flexmarkdown sheet.
So this is my current (example) layout and I'm trying to build a reactive selector that takes the mineral type input on the left side and then re-renders
the entire table to only select for "Rock Type = Type 1" in this case.
Full source #pastebin here: Link
My current selector:
```{r}
selectInput("input_type","Mineral Type:", data$`Rock Type`)
```
I'm been able to achieve this by doing the below but I'd also like to build in a selection for all/no groupings.
```{r}
dataInput <- reactive({
subset(data,data$`Rock Type` == input$input_type)
})
renderDataTable(dataInput())
```
You can add an All option to your selectInput, that you check in the reactive:
```{r}
selectInput("input_type","Mineral Type:", c("All", unique(data$`Rock Type`))
```
```{r}
dataInput <- reactive({
if(input$input_type=="All")
data
else
subset(data,`Rock Type` == input$input_type)
})
renderDataTable(dataInput())
```

R Markdown Shiny renderPlot list of plots from lapply

I am developing an R Markdown Shiny document to:
Subset a data frame to include the "date" column and some numeric data columns. The way the shiny user input is set up, you select radio buttons for the data columns to include, then hit the "Subset Data" button to create d() - NO PROBLEM:)
Generate a list of plots (plotList), one for each numeric data column (plotted against the date column). I am using the openair package timePlot function to generate the plots, and lapply to generate the list of plot objects (plotList) - NO PROBLEM:)
use renderPlot to output all the plots in plotList to the R Markdown document - PROBLEM:(
I know there have been similar questions (e.g https://gist.github.com/wch/5436415/, Reactivity in R shiny with toy example, and dynamically add plots to web page using shiny), and please believe me I have tried and tried (e.g. using a for loop in stead of lapply-not my preference, but if it worked then who cares; adding local() and/or observe(); etc). No matter what I do I can't get it to to work. I am new to R Markdown and to Shiny, I just can't figure this out - please help!
Here is a reproducible example (to be run as an R markdown shiny document).
First the chunk that creates a reactive dataset d():
```{r reactive-dataset, echo=FALSE,message=FALSE}
library(openair)
library(dplyr)
data<-mydata[1:50,]
print(tbl_df(data))
inputPanel(
checkboxGroupInput(inputId="p",
label="select pollutants to plot",
choices=names(data)[-1]
),
actionButton(inputId="import",
label="Subset Data")
)
d<-eventReactive(input$import,{
d<-data %>% select(date,one_of(input$p))
})
renderPrint({tbl_df(d())})
```
Now the second chunk, to create plotList and output it (PART THAT DOESN'T WORK):
Attempt 1: only last plot is displayed
```{r plot,echo=FALSE,message=FALSE}
renderPlot({
i<-names(d())[-1]
tp<-function(x){
p<-timePlot(d(),
pollutant=print(x),
main="Minute Validation",
ylab="Minute Conc. (ug/m3 or ppb)",
key=T)
p$plot
}
lapply(i,tp)
})
```
Attempt 2 (based on Reactivity in R shiny with toy example). No plots are displayed
```{r plot,echo=FALSE,message=FALSE}
plotList<-reactive({
i<-names(d())[-1]
tp<-function(x){
p<-timePlot(d(),
pollutant=print(x),
main="Minute Validation",
ylab="Minute Conc. (ug/m3 or ppb)",
key=T)
p$plot
}
lapply(i,tp)
})
observe({
for (j in 1:length(plotList())){
local({
my_j<-j
renderPlot({plotList()[[my_j]]})
})#end local
} #end for loop
}) #end observe
```
I have fiddled with this endlessly, referring the to similar questions that I have linked to above.
[New answer]
I finally got this worked out. The key is to exactly follow the example in the third link of your post, using renderUI first!
```{r plot,echo=FALSE,message=FALSE}
tp_list <- reactive({
i<-names(d())[-1]
tp<-function(x){
p<-timePlot(d(),
pollutant=print(x),
main="Minute Validation",
ylab="Minute Conc. (ug/m3 or ppb)",
key=T)
p$plot
}
lapply(i, tp)
})
renderUI({
plot_output_list <- lapply(1:length(tp_list()), function(i) {
plotname <- paste("plot", i, sep="")
plotOutput(plotname)
})
do.call(tagList, plot_output_list)
})
observe({
for (i in 1:length(tp_list())) {
local({
my_i <- i
plotname <- paste("plot", my_i, sep="")
output[[plotname]] <- renderPlot({
tp_list()[[my_i]]
})
})
}
})
```
[Original answer based on lattice panels]
This is not exactly what you want, but I got all the plots displayed in one plot.
```{r plot,echo=FALSE,message=FALSE}
renderPlot({
i<-names(d())[-1]
tp<-function(x){
p<-timePlot(d(),
pollutant=print(x),
main="Minute Validation",
ylab="Minute Conc. (ug/m3 or ppb)",
key=T)
p$plot
}
tp(i)
})
```

Problems using ggvis in rMarkdown with variables

Hi having a couple of problems
a) creating the correct text to pass variables to ggvis - not even sure aes_string is applicable
b) The plot propagates in browser rather than rendering in the rmarkdown document
Here is an example
---
title: "Untitled"
author: "pssguy"
date: "Sunday, August 24, 2014"
output: html_document
runtime: shiny
---
```{r, echo = FALSE, message=FALSE}
library(ggplot2)
library(ggvis)
library(dplyr)
selectInput("category3", "Choose Dataset:", c("mpg", "disp", "qsec"))
# ggplot renders correctly within renderPlot
renderPlot({
ggplot(mtcars,aes_string(input$category3,"disp"))+geom_point()
})
# ggvis works within document with hard coded info
mtcars %>% ggvis(~wt,~disp)
mtcars %>% ggvis(aes_string(paste("~",input$category3,","),"~disp"))
#Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
# This needs correcting anyways
renderPlot({
mtcars %>% ggvis(aes_string(paste("~",input$category3,","),"~disp"))
})
# <text>:1:7: unexpected ',' 1: ~ mpg ,
# even if the above is corrected the plot opens in a browser rather than the document
renderPlot({
mtcars %>% ggvis(~wt,~disp)
})
```
TIA
This should do it:
---
title: "Untitled"
output: html_document
runtime: shiny
---
```{r, echo = FALSE, message=FALSE}
library(ggplot2)
library(ggvis)
library(dplyr)
selectInput("category3", "Choose Dataset:", c("mpg", "disp", "qsec"))
# ggplot renders correctly within renderPlot
renderPlot({
print(input$category3)
ggplot(mtcars,aes_string(input$category3,"disp"))+geom_point()
})
# ggvis with dynamically changing columns
reactive({
if (!is.null(input$category3))
col <- input$category3
else
col <- "mpg"
mtcars %>% ggvis(prop("x", as.name(col)), ~disp)
}) %>% bind_shiny('foo')
ggvisOutput('foo')
```
It's a little complicated because you need a NULL check for the category, and you need to explicitly tell knitr to put a ggvis output on the page.