Incomplete CSV/Excel rows downloaded from DT buttons through RMarkdown-Shiny - r

I have the following RMarkdown Shiny document:
---
title: "Title"
runtime: shiny
output:
flexdashboard::flex_dashboard:
vertical_layout: scroll
theme: bootstrap
orientation: rows
---
```{r setup, include=FALSE}
library(flexdashboard)
```
Rows {data-height=400}
-----------------------------------------------------------------------
### Table
``` {r show_table}
library(DT)
library(ggplot2)
renderDataTable( {
dat <- diamonds
},
extensions = c('Scroller','Buttons'),
class = 'compact cell-border stripe', rownames = FALSE,
filter = list( position = 'top', clear = FALSE, plain =TRUE ),
options = list(
deferRender = FALSE,
scrollY = 200,
scroller = TRUE,
dom = 'Bfrtip',
buttons = c('csv', 'excel')
)
)
```
Which produces this document:
After I download the Excel file, the number of rows is just ~90 lines
not complete 53,940 entries. Why is that and how can I fix it?

By default DT uses Server-side Processing so only the visible data are sent to the browser. That is why the Excel file only contains the visible data (if you remove scrollY = 200 and scroller = TRUE this becomes very clear).
To download all data you need to disable Server-side Processing by including server = FALSE, e.g.
class = 'compact cell-border stripe', rownames = FALSE,
server = FALSE,
filter = list( position = 'top', clear = FALSE, plain =TRUE ),
Unfortunately, this makes loading and browsing the table extremely slow (on my computer at least).
BTW: Your code depends on the diamonds dataset which is part of ggplot2.

Related

shinyWidgets pickerInput width issue overflow off sidebar

I am using shinyWidgets pickerInput within a flexdashboard sidebar. My issue is that when the options in the pickerInput are too wide they get cut off within the width of the sidebar which makes it so you cannot read the options, see which are selected, or see the deselect all button. Is there a way to have the pickerInput dropdown overflow off of the sidebar and onto the body of the page?
As an intermediate solution I have found that you can use:
choicesOpt = list(
content = stringr::str_trunc(sort(unique(COLUMN_NAME)), width = 25))
To truncate the text in the pickerInput so that you are able to see which options are selected and all of the buttons but you are still not able to read each option fully.
Edit:
Adding reprex - Looking to have the filter drop down open over the body so that everything is visible.
---
title: "TEST"
runtime: shiny
output:
flexdashboard::flex_dashboard:
orientation: rows
---
```{r setup, include=FALSE}
library(dplyr)
library(shiny)
library(DT)
library(shinyWidgets)
Name <- c("LONNGGGGGGGGGGGGGGG TEXXTTTTTTTTTTTTTTTTTT", "Bill", "Maria", "Ben", "Tina")
Age <- c(23, 41, 32, 58, 26)
df <- data.frame(Name, Age)
```
Sidebar {.sidebar}
=======================================================================
### Filters
```{r}
pickerInput(
inputId = "name",
label = "test",
choices = sort(unique(df$Name)),
selected = sort(unique(df$Name)),
multiple = TRUE,
options = list(
`actions-box` = TRUE,
`selected-text-format` = paste0("count > ", length(sort(unique(df$Name))) -1),`count-selected-text` = "All Selected")
)
```
TEST
=======================================================================
Row
-------------------------------------
```{r}
filtered_data <-
reactive ({
req(input$name)
df %>%
filter(Name %in% input$name)
})
renderDataTable(filtered_data(), class = 'cell-border stripe',
extensions = 'Buttons',
rownames = FALSE,
options = list(
columnDefs = list(list(className = 'dt-center',width = '100px', targets = "_all"))),fillContainer=TRUE)
```
This may have unintended side effects but here's a workaround to force the picker dropdown to not get cutoff.
You can add your own css class to the Sidebar section inside the {}. I used .my-class as a placeholder. Then I inserted a css chunk and added .my-class to the .section.sidebar classes from flexdashboard. If you don't do that then that css will overwrite the class. Most likely because it's loaded afterwards.
Also in the reprex provided, for whatever reason the choices were the not the actual values but instead the level positions.
So I used sort(unique(Name)) instead of sort(unique(df$Name))
```{css, echo=FALSE}
.section.sidebar.my-class {
overflow: visible;
z-index: 10;
}
```
Sidebar {.sidebar .my-class}
=======================================================================
...
Option 2: Truncate choices
The above option works as long as the height of the sidebar does not exceed the height of the browser window. Ideally you want overflow-x: visible and overflow-y: scroll. However I'm not sure if that's possible on the same div with position fixed.
Instead you could truncate your options so they fit in the window. If you want more text to be displayed you can increase the width of the sidebar.
cs = sort(unique(Name)
pickerInput(
inputId = "name",
label = "test",
choices = cs,
selected = cs,
multiple = TRUE,
options = list(
`actions-box` = TRUE,
`selected-text-format` = paste0("count > ", length(sort(unique(df$Name))) -1),`count-selected-text` = "All Selected"
),
choicesOpt = list(
content = stringr::str_trunc(cs, width = 18)
)
)

searchPanes extension in Rmarkdown

I am trying to get the searchPanes extension from DT to work in an rmarkdown file (https://rstudio.github.io/DT/extensions.html). I can get it to work with datatable but not with renderDataTable and reactive statement. Attached is a working example that one tab shows it working and the other tab showing the issue. Any advice/recommendation is appreciate.
My code:
---
title: "Filter_example"
output: flexdashboard::flex_dashboard
runtime: shiny
date: "`r Sys.Date()`"
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = F)
library(DT)
library(tidyverse)
```
# Sidebar {.sidebar data-width="200"}
```{r sidebar, echo=FALSE}
selectizeInput('color', label ='color', choices = diamonds$color ,
multiple = TRUE,
options = list(maxItems = 5,
placeholder = 'Search Here...'))
```
# Diamonds Are Forever
```{r echo=FALSE}
diamonds %>%
datatable(
rownames = F,
extensions = c("SearchPanes", "Select", "Buttons"),
options = list(
language = list(searchPanes = list(collapse = "Filter Rows")),
scrollX= "30vw",
scrollY = "45vh",
dom = "Blfrtip",
buttons = list("searchPanes")
),
selection = 'none'
)
```
# Diamonds Are Forever renderDataTable
```{r echo=FALSE}
diamonds_dd <- reactive({
if (is.null(input$color)){
diamonds
}
else if(!is.null(input$color)) {
diamonds %>%
filter(color %in% input$color)
}
})
DT::renderDataTable(diamonds_dd(),extensions = c("SearchPanes", "Select", "Buttons"),
options = list(
scrollX= "30vw",
scrollY = "45vh",
dom = "Blfrtip",
buttons = list("searchPanes"),
columnDefs = list(
list(searchPanes = list(show = FALSE), targets = 3:5),
list(searchPanes = list(controls = FALSE), targets = 0:2),
list(className = "dt-center", targets = 0:5)
)
),
selection = 'none'
)
```
You need server = FALSE.
DT::renderDataTable(
diamonds_dd(), extensions = c("SearchPanes", "Select", "Buttons"),
options = list(
scrollX= "30vw",
scrollY = "45vh",
dom = "Blfrtip",
buttons = list("searchPanes"),
columnDefs = list(
list(searchPanes = list(show = FALSE), targets = 3:5),
list(searchPanes = list(controls = FALSE), targets = 0:2),
list(className = "dt-center", targets = 0:5)
)
),
selection = 'none',
server = FALSE
)
However, this is not recommended for a large dataset like diamonds. It sends all rows to users which is unnecessary and takes a long time.

How to add tab sets into flexdashboard?

I am working with flexdashboard and I am trying to add sub tabset into tabset . Below you can see my code:
---
title: "Test APPLICATION"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
---
```{r setup, include=FALSE}
library(flexdashboard)
library(data.table)
library(tidyr)
library(dplyr)
library(tidyverse)
library(knitr)
library(DT)
library(rpivotTable)
library(biclust)
data(BicatYeast)
data=data.frame(data(BicatYeast))
```
# Intro
Testing application
Tabset 1
=======================================================================
Row {.tabset}
-----------------------------------------------------------------------
### Notes
### Sub tabset 1
```{r,eval=TRUE}
rpivotTable(
data,
aggregatorName = "Integer Sum",
vals="Total",
cols = "Test",
width="100%",
height="400px",
rendererName = "Table"
)
```
### Sub tabset 2
```{r,eval=TRUE}
rpivotTable(
data,
aggregatorName = "Integer Sum",
vals="Total",
cols = "Test",
width="100%",
height="400px",
rendererName = "Table"
)
```
Tabset 2
=======================================================================
Row {.tabset}
-----------------------------------------------------------------------
### Sub tabset 1
```{r,eval=TRUE}
datatable(data,
caption = "Test",
rownames = T,
filter = "top",
class = 'cell-border stripe',
extensions='Buttons',
options = list(
pageLength = 50,
dom = 'Blfrtip',
buttons=c('copy','csv','excel','pdf','print'),
lengthMenu = list(c(10,25,50,-1),c(10,25,50,"All"))
))
```
### Sub tabset 2
```{r,eval=TRUE}
datatable(data,
caption = "Test",
rownames = T,
filter = "top",
class = 'cell-border stripe',
extensions='Buttons',
options = list(
pageLength = 50,
dom = 'Blfrtip',
buttons=c('copy','csv','excel','pdf','print'),
lengthMenu = list(c(10,25,50,-1),c(10,25,50,"All"))
))
```
Now, I want to put additional tab sets under Sub tabset 1. Can anybody help me on how to solve this problem and add additional tab sets (two or three)?

Rmarkdown Download data with download button for that row

Update
renderdatatable doesnt show actionbutton, renderDT shows but not able to just download the table although i can see the actionbutton being triggered with cat statement
I'm new to markdown trying to build a markdown application which needs to download data depending on the action/download button. In my example below, id like to have a downloadButton or downloadLink to download the row contents of the download button row, if i click on the first action button then id like to download mtcars 1st row values for mpg, cyl, disp to a csv or excel.
I have a fairly large subset in the actual application so i can filter accordingly.
The problem is i am not getting an action button but just raw html in my DT, not sure if i am missing small details.
---
title: "Download data with download button"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
runtime: shiny
---
```{r setup, include=FALSE}
library(flexdashboard)
library(DT)
library(downloadthis)
library(dplyr)
```
```{r, echo=FALSE}
shinyInput <- function(FUN, n, id, ...) {
vapply(seq_len(n), function(i){
as.character(FUN(paste0(id, i), ...))
}, character(1))
}
downloadButtonRmd <- function (outputId, label = "Download", class = NULL, ...) {
tags$a(id = outputId, class = paste("btn btn-default shiny-download-link",
class), href = "", target = "_blank", download = NA,
icon("download"), label, ...)
}
tab <- data.frame(head(mtcars[1:3]))
tab <- tab %>% mutate(
dl1 = shinyInput(actionButton, nrow(.), 'button_', label = "Download", onclick = 'Shiny.onInputChange(\"select_button\", this.id)' ),
dl2 = shinyInput(downloadButtonRmd, nrow(.), 'button_', label = "Download",onclick = 'Shiny.onInputChange(\"select_button1\", this.id)' ))
# renderDataTable({
# tab %>%
# datatable(extensions = 'Buttons',
# options = list(dom = 'Blfrtip',
# buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
# lengthMenu = list(c(10,25,50,-1),
# c(10,25,50,"All"))))
# })
renderDT({
datatable(tab,
options = list(pageLength = 25,
dom = "rt"),
rownames = FALSE,
escape = FALSE)})
observeEvent(input$select_button1, {
selectedRow <<- as.numeric(strsplit(input$select_button1, "_")[[1]][2])
cat(input$select_button1)
downloadHandler(filename = "Academic Report.csv",
content = function(file) {write.csv(tab[selectedRow,1:3], file, row.names = FALSE)},
contentType = "text/csv")
})
```
I've read through these links and many others but i'm unable to get what I intended
RShiny Download Button Within RMarkdown
R Shiny: Handle Action Buttons in Data Table
Thanks
Here is a way with the downloadthis package.
---
title: "DT download row"
author: "Stéphane Laurent"
date: "21/03/2022"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(DT)
library(downloadthis)
htmltools::tagList( # for the icons
rmarkdown::html_dependency_font_awesome()
)
```
```{r}
dat <- mtcars
dat[["Download"]] <- vapply(1L:nrow(mtcars), function(i){
as.character(
download_this(
.data = mtcars[i, ],
output_name = paste0("mtcars - row ", i),
output_extension = ".csv",
button_label = "Download",
button_type = "primary",
icon = "fa fa-save",
csv2 = FALSE,
self_contained = TRUE
)
)
}, character(1L))
```
```{r}
datatable(
dat,
escape = FALSE,
options = list(
columnDefs = list(
list(targets = ncol(dat), orderable = FALSE),
list(targets = "_all", className = "dt-center")
)
)
)
```
Of course that won't work if you edit the table.

How to display image inside column with DT in R Markdown or shiny?

---
title: "Untitled"
runtime: shiny
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r}
df <- data.frame(image = "http://www.ufotm.com/data/attachment/forum/201203/11/110705gf50r55yqcka5ffz.jpg", title = "here is a title")
DT::renderDataTable(df,
escape = FALSE,
rownames = FALSE,
extensions = 'Buttons', options = list(
dom = 'lBfrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
)
)
```
I have the image url. I try to insert image in a rmarkdown or shiny app. I prefer DT library because I can download excel file then. How can I do that?
PS: I want to provide excel or pdf file for my user to download as well.
I try to use DataTables Options, and find a related question. I tried the below code and it shows error.
---
title: "Untitled"
runtime: shiny
output: html_document
---
df <- data.frame(image = "http://www.ufotm.com/data/attachment/forum/201203/11/110705gf50r55yqcka5ffz.jpg", title = "here is a title")
DT::renderDataTable(df,
escape = FALSE,
rownames = FALSE,
extensions = 'Buttons', options = list(
dom = 'lBfrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
columnDefs = list(list(targets = 1,
data = "img",
render = JS(
'function ( url, type, full) {',
'return '<img height="75%" width="75%" src="'+full[7]+'"/>';',
'}'
)
))
)
)
You can use html tags and use escape = FALSE as below:
---
title: "Untitled"
runtime: shiny
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r}
df <- data.frame(image = c('<img src="http://www.ufotm.com/data/attachment/forum/201203/11/110705gf50r55yqcka5ffz.jpg" height="52"></img>' ), title = "here is a title")
DT::renderDataTable(df, escape = FALSE)
```
You will get something like this:

Resources