R Shiny - How to round numbers, convert to percentage and download .csv-file

Viewed 2423

I wrote a shiny app which will be used for searching and downloading a quite large dataset. The app works and is nearly done, but some functionalities do not work as I want:

  • I tried several ways of adding a function in order to download the chosen data as .csv-file. All of them failed and I was only able to download all data instead of the displayed ones.
  • I was not able to include a function to round data and show some columns as percentage instead of numbers. The formatRound() function within datatable() works well and I would like to use it, but the problem is that I was not able to include it in the server function. Since the user should get the whole number (with all numbers also behind the comma) for his or her work, the data should only be rounded when displayed. If I would be able to fix the rounding, the percentage problem will also be solved, since I would use the similar function formatPercentage().

I made an example using the mtcars-data and removed all wrong or not-working codes for the download and rounding problem. Any hints how I could solve my problem would be extremely appreciated! Thanks in advance!

EDIT3: Rounding problem solved with the code below thanks to @Claud H. The download function exports an empty file (no file-type) named download. Do you have any idea where the error is?

EDIT4: problems solved thanks to @Claud H. I changed mt_cars_filtered()[, c(input$results_columns_selected)]into mt_cars_filtered()[, input$indicator]. Also, I didn't know first that I had to open the web browser to download the data.

      library(tidyverse)
      library(shiny)
      library(shinythemes)
      library(DT)
      library(ggthemes)

      ui <- fluidPage(

        sidebarLayout(

    sidebarPanel(width=3,
                 h3("title", align = 'center'),

                 checkboxGroupInput("cylinder", "Cylinder", choices = c(4,6), selected = c(4)),

                 checkboxGroupInput('indicator', label = 'Indicators', choices = colnames(mtcars)[1:7],
                                    selected = colnames(mtcars)[c(1:7)]),

                 fluidRow(p(class = 'text-center', downloadButton('download', label = 'Download')))),


    mainPanel(
      tabsetPanel(
        tabPanel('Table',
                 DT::dataTableOutput('results'))

      )
    )
        ))


      server <- function(input, output){

        mtcars_filtered <- reactive({
          mtcars %>%
            filter(cyl %in% input$cylinder)
        })

        # Output Table
        output$results <- DT::renderDataTable({
          columns = input$indicator
          mtcars_filtered()[, columns, drop = FALSE] %>%
      datatable(style = 'bootstrap', selection = list(target = 'column'), options = list(paging = FALSE, dom = 't')) %>%
      formatRound(input$indicator[grep('t', input$indicator)], 2)
        })

        # Download Data
        output$download <- downloadHandler(
          filename = function() { paste('filename', '.csv', sep = '') },
          content = function(file) {
            write.csv(mtcars_filtered()[,input$indicator], file, row.names = FALSE)
    })
      }

      shinyApp(ui = ui, server = server)
1 Answers

Suggest looking at ?"%>%" from magrittr package

Also, check this and this answers on SO.

Your table should be fine with this kind of syntax

output$results <- DT::renderDataTable({
    columns = input$indicator
    mtcars_filtered()[, columns, drop = FALSE] %>% 
      datatable() %>%
      formatCurrency( input your code here) %>%
      formatPercentage( and so on ... )
  }, style = 'bootstrap', options = list(paging = FALSE, dom = 't')) 

Also, I didnt quite get the question about downloading. If you want to download a data FROM server, use downloadHandler() function. Something like:

output$save_data <- downloadHandler(
  filename = function() { paste("filename", '.csv', sep = '') },
  content = function(file) {
    write.csv(mydata(), file, row.names = FALSE)
  })

and downloadButton("save_data", "download") in ui.R

edit: as per your changes, download isn't working because you got wrong columns selected: there is no table called tableId, and you need to take the columns from the table called results:

write.csv(mtcars_filtered()[, c(input$results_columns_selected)], file, row.names = FALSE)

as of rounding problem, you can use your indicator variable to see if column is selected input$indicator %in% c('drat', 'qsec', 'wt') then use subsetting to select only columns with TRUE, if there are any: formatRound(input$indicator[input$indicator %in% c('drat', 'qsec', 'wt')], 2)

edit2 Seems I've understood everything you wanted to do right. To select columns in the downloadHandler function based on your checkboxes , use indicator variable to filter it:

mtcars_filtered()[, input$indicator]

Otherwise, if you want to select them from the table itself with the mouse clicks, use input$results_columns_selected, like this:

mtcars_filtered()[, c(input$results_columns_selected)]
Related