32

I want to build a shiny app that gets matrix data as input and returns a table based on some operations on it as output. By search I find that ShinyTable package could be useful. I tried below shiny codes but the result app appears gray out and without result.

library(shinyTable)
shiny::runApp(list(
  ui=pageWithSidebar(
    headerPanel('Simple matrixInput')
    ,
    sidebarPanel(
      htable("tbl")
      ,
      submitButton("OK")
    )
    ,
    mainPanel(

      tableOutput(outputId = 'table.output')
    ))
  ,
  server=function(input, output){
    output$table.output <- renderTable({
      input$tbl^2
    }
    , sanitize.text.function = function(x) x 
    )
  }
))

Any Idea?

4
  • 1
    It's is a known issue, it occured with new versions of shiny "because of the way Shiny now handles custom inputs" see : groups.google.com/forum/#!topic/shiny-discuss/F8aAtv85ZGs Commented Mar 8, 2014 at 20:15
  • Thanks Julien, Can we be hopeful for solve is? Commented Mar 9, 2014 at 7:23
  • Please have look at stackoverflow.com/questions/21910853/subsetting-shinytable and the shiny and shinyTable versions I am using there. Commented Mar 11, 2014 at 9:24
  • I tried to install and load both shiny and shinyTable like you, but I got this error: "Error in get(Info[i, 1], envir = env) : lazy-load database 'P' is corrupt In addition: Warning message: In get(Info[i, 1], envir = env) : internal error -3 in R_decompress1 Error: package or namespace load failed for ‘shiny’" Commented Mar 11, 2014 at 12:10

4 Answers 4

36

The shinyTable package has been greatly improved in the rhandsontable package.

Here is a minimal function that takes a data frame and runs a shiny app allowing to edit it and to save it in a rds file:

library(rhandsontable)
library(shiny)

editTable <- function(DF, outdir=getwd(), outfilename="table"){
  ui <- shinyUI(fluidPage(

    titlePanel("Edit and save a table"),
    sidebarLayout(
      sidebarPanel(
        helpText("Shiny app based on an example given in the rhandsontable package.", 
                 "Right-click on the table to delete/insert rows.", 
                 "Double-click on a cell to edit"),

        wellPanel(
          h3("Table options"),
          radioButtons("useType", "Use Data Types", c("TRUE", "FALSE"))
        ),
        br(), 

        wellPanel(
          h3("Save"), 
          actionButton("save", "Save table")
        )        

      ),

      mainPanel(

        rHandsontableOutput("hot")

      )
    )
  ))

  server <- shinyServer(function(input, output) {

    values <- reactiveValues()

    ## Handsontable
    observe({
      if (!is.null(input$hot)) {
        DF = hot_to_r(input$hot)
      } else {
        if (is.null(values[["DF"]]))
          DF <- DF
        else
          DF <- values[["DF"]]
      }
      values[["DF"]] <- DF
    })

    output$hot <- renderRHandsontable({
      DF <- values[["DF"]]
      if (!is.null(DF))
        rhandsontable(DF, useTypes = as.logical(input$useType), stretchH = "all")
    })

    ## Save 
    observeEvent(input$save, {
      finalDF <- isolate(values[["DF"]])
      saveRDS(finalDF, file=file.path(outdir, sprintf("%s.rds", outfilename)))
    })

  })

  ## run app 
  runApp(list(ui=ui, server=server))
  return(invisible())
}

For example, take the following data frame:

> ( DF <- data.frame(Value = 1:10, Status = TRUE, Name = LETTERS[1:10],
                    Date = seq(from = Sys.Date(), by = "days", length.out = 10),
                    stringsAsFactors = FALSE) )
   Value Status Name       Date
1      1   TRUE    A 2016-08-15
2      2   TRUE    B 2016-08-16
3      3   TRUE    C 2016-08-17
4      4   TRUE    D 2016-08-18
5      5   TRUE    E 2016-08-19
6      6   TRUE    F 2016-08-20
7      7   TRUE    G 2016-08-21
8      8   TRUE    H 2016-08-22
9      9   TRUE    I 2016-08-23
10    10   TRUE    J 2016-08-24

Run the app and have fun (especially with the calendars ^^):

enter image description here

Edit the handsontable:

enter image description here

Click on the Save button. It saves the table in the file table.rds. Then read it in R:

> readRDS("table.rds")
   Value Status    Name       Date
1   1000  FALSE Mahmoud 2016-01-01
2   2000  FALSE       B 2016-08-16
3      3  FALSE       C 2016-08-17
4      4   TRUE       D 2016-08-18
5      5   TRUE       E 2016-08-19
6      6   TRUE       F 2016-08-20
7      7   TRUE       G 2016-08-21
8      8   TRUE       H 2016-08-22
9      9   TRUE       I 2016-08-23
10    10   TRUE       J 2016-08-24
Sign up to request clarification or add additional context in comments.

1 Comment

Hi @Stéphane Laurent : I am new-ish to shiny, I am trying to understand the code within the Observer of your solution, what's the purpose of this code block? If I skip this piece of the code what functionality will I miss?
7

If you are looking for a solution that users can input their matrix data as in excel you could probably take a look at the package "shinySky" and more specifically to its component "Handsontable Input/Output". The relevant web address is: https://github.com/AnalytixWare/ShinySky.

Another similar solution would be the package shinyTable. You can find more information at https://github.com/trestletech/shinyTable

Comments

4

You could use hotable("matrixTable") from the shinysky package.

library(shiny, shinysky)
shinyApp(
  ui     = shinyUI (wellPanel(hotable("matrixTable"),hotable("resultTable"))),

  server = shinyServer (function(input, output) {
    A = matrix(c(1:6), nrow=2) # init - input matrix A
    output$matrixTable <- renderHotable({data.frame(A)}, readOnly = FALSE)

    R = matrix(rep(0,6), nrow=2) # init - result matrix R
    output$resultTable <- renderHotable({data.frame(R)}, readOnly = TRUE)

    observe({  # process matrix
      df <- hot.to.df(input$matrixTable)
      if(!is.null(df)) {    # ensure data frame from table exists
        B = data.matrix(df) # ensure its numeric
        R = B^2             # some matrix operation
        output$resultTable <- renderHotable({data.frame(R)})
      }
    }) # end of observe
  }) # end of server
)

In the user interface ui the input "matrixTable" and the "resultTable" are visualised. The server initialises these tables, such that matrixTable can be edited. That means you can copy & paste your data from Excel, or change values manually. The observe function is activated, whenever a change is noticed in the input matrixTable. We extract a data frame df with ho.to.df from that table. In case its not NULL we convert it into a matrix, and apply some matrix operations (e.g. square each element) and return the output as a new matrix.

This solution was obtained by using Christo's suggestion and Stephane's approach.

1 Comment

Got the warning error package ‘shinysky’ is not available (for R version 3.6.3)
2

I am not sure if the following is what you are looking for, but here goes. Assuming that you can input the matrix as a text/csv file, then the following modification to your code above would work. This is directly from the Shiny tutorial: http://rstudio.github.io/shiny/tutorial/#uploads

shiny::runApp(list(
    ui=pageWithSidebar(
        headerPanel('Simple matrixInput')
        ,
        sidebarPanel(
            fileInput('file1', 'Choose CSV File',
              accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv'))
            ,
            tags$hr(),
            checkboxInput('header', 'Header', TRUE),
            radioButtons('sep', 'Separator',
                 c(Comma=',',
                   Semicolon=';',
                   Tab='\t'),
                 'Comma'),
            radioButtons('quote', 'Quote',
                 c(None='',
                   'Double Quote'='"',
                   'Single Quote'="'"),
                 'Double Quote')
        )
        ,
        mainPanel(

            tableOutput(outputId = 'table.output')
        ))
    ,
    server=function(input, output){
        output$table.output <- renderTable({

        inFile <- input$file1

       if (is.null(inFile))
        return(NULL)

        tbl <- read.csv(inFile$datapath, header=input$header, sep=input$sep, quote=input$quote)
        return(tbl^2)
        })
    }
))

enter image description here

1 Comment

Thanks for your response rmk. I'm no interested in uploading files. I need a solution that users can input their matrix data in a excel like table.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.