In R Shiny, isTruthy() function is not working the way I think it should

Curious Jorge - user9788072

I believe I have a fundamental misunderstanding of how the isTruthy() function works.

In the below MWE, inputs into the first matrix are summed and plotted straight-line over 10 periods. However this works ONLY IF the matrix 2 creation function is commented-out like in this MWE. When matrix 2 creation is un-commented (matrix 2 does the same thing as matrix 1: inputs are summed and plotted, but plotted as a separate line), matrix 1 inputs are no longer summed and plotted.

The issue appears to lie in if(isTruthy(input$matrix2)){... under the plotData <- reactive({...} function in the server section. I thought if(isTruthy(...) in this context meant if there are manual inputs into matrix 2, then plot matrix 2, otherwise skip ahead to the else{...} and just plot matrix 1. (Note that in the larger App this code is derived from, matrix 2 is rendered in modal dialog, thus the reason why plotting has been broken up this way).

How would I change this code so that matrix 2 is only plotted if there are manual inputs into matrix 2; otherwise plot matrix 1? In order to solve a larger problem I have, I'd like matrix 1 to plot correctly even when matrix 2 is present.

library(dplyr)
library(ggplot2)
library(shiny)
library(shinyMatrix)

sumMat <- function(x){return(rep(sum(x,na.rm = TRUE), 10))}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      matrixInput("matrix1",
                  value = matrix(c(60,5), ncol = 2, dimnames = list(NULL,c("X","Y"))),
                  rows = list(extend = TRUE, delete = TRUE), class = "numeric"),
      # matrixInput("matrix2",
      #             label = "Matrix 2 (Value Y applied in Period X):",
      #             value = matrix(c(60,5),ncol=2,dimnames=list(NULL,rep("Scenario 1",2))),
      #             rows = list(extend = TRUE, delete = TRUE),
      #             cols = list(extend = TRUE, delta = 2, delete = TRUE, multiheader = TRUE),
      #             class = "numeric"),
    ),
    mainPanel(plotOutput("plot"))  
  )    
)

server <- function(input, output, session){
  
  observeEvent(input$matrix1, {
    tmpMat1 <- input$matrix1
    if(any(rownames(input$matrix1) == "")){rownames(tmpMat1) <- paste("Row", seq_len(nrow(input$matrix1)))}
    updateMatrixInput(session, inputId = "matrix1", value = tmpMat1)
  })
  
  plotData <- reactive({
    tryCatch(
      if(isTruthy(input$matrix2)){
        lapply(seq_len(ncol(input$matrix2)/2), 
               function(i){
                 tibble(Scenario = colnames(input$matrix2)[i*2-1],
                        X = seq_len(10),Y = sumMat(input$matrix2[,(i*2-1):(i*2), drop = FALSE]))
               }) %>% bind_rows()
      } else
        {tibble(Scenario = "Scenario 1", X = seq_len(10),Y = sumMat(input$matrix1))},
      error = function(e) NULL)
  })
  
  output$plot <- renderPlot({
    req(plotData())
    plotData() %>% ggplot() + geom_line(aes(x = X, y = Y, colour = as.factor(Scenario)))
  })
}

shinyApp(ui, server)
Curious Jorge - user9788072

See error explanation in CuriousJorge response to Limey comment (incorrect use of isTruthy(), flawed if/then/else logic in the plotData() function).

Note how matrix 1 inputs "downstream" to matrix 2 as scenario 1.

Below is the resolved code:

library(dplyr)
library(ggplot2)
library(shiny)
library(shinyMatrix)

sumMat <- function(x){return(rep(sum(x,na.rm = TRUE), 10))}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      matrixInput("matrix1",
                  label ="Matrix 1 (scenario 1):",
                  value = matrix(c(60,5), nrow = 1, ncol = 2, dimnames = list(NULL,c("X","Y"))),
                  rows = list(extend = TRUE, delete = TRUE),
                  class = "numeric"),
      matrixInput("matrix2",
                  label = "Matrix 2:",
                  value = matrix(c(60,5), ncol = 2, dimnames = list(NULL, rep("Scenario 1", 2))),
                  rows = list(extend = TRUE, delete = TRUE),
                  cols = list(extend = TRUE, delta = 2, delete = TRUE, multiheader = TRUE),
                  class = "numeric")
      ),
      mainPanel(plotOutput("plot"))
  )
)

server <- function(input, output, session){
  
  observeEvent(input$matrix1, {
    a <- apply(input$matrix2,2,'length<-',max(nrow(input$matrix2),nrow(input$matrix1)))
    b <- apply(input$matrix1,2,'length<-',max(nrow(input$matrix2),nrow(input$matrix1)))
    c <- if(length(a) == 2){c(b)} else {c(b,a[,-1:-2])}
    d <- ncol(input$matrix2)
    tmpMat2 <- matrix(c(c), ncol = d)
    colnames(tmpMat2) <- paste("Scenario",rep(1:ncol(tmpMat2),each=2,length.out=ncol(tmpMat2)))

    if(any(rownames(input$matrix1) == "")){
      tmpMat1 <- input$matrix1
      rownames(tmpMat1) <- paste("Row", seq_len(nrow(input$matrix1)))
      updateMatrixInput(session, inputId = "matrix1", value = tmpMat1)
      }
    updateMatrixInput(session, inputId = "matrix2", value = tmpMat2)
  })
  
  observeEvent(input$matrix2, {
    if(any(colnames(input$matrix2) == "")){
      tmpMat2 <- input$matrix2
      colnames(tmpMat2) <- paste("Scenario",rep(1:ncol(tmpMat2),each=2,length.out=ncol(tmpMat2)))
      updateMatrixInput(session, inputId = "matrix2", value = tmpMat2)
      }
    if(any(rownames(input$matrix2) == "")){
      tmpMat2 <- input$matrix2
      rownames(tmpMat2) <- paste("Row", seq_len(nrow(input$matrix2)))
      updateMatrixInput(session, inputId = "matrix2", value = tmpMat2)
      }
    input$matrix2
  })
  
  plotData <- reactive({
    tryCatch(
      lapply(seq_len(ncol(input$matrix2)/2), 
             function(i){
               tibble(
                 Scenario = colnames(input$matrix2)[i*2-1],
                 X = seq_len(10),
                 Y = sumMat(input$matrix2[,(i*2-1):(i*2), drop = FALSE])
               )
             }) %>% bind_rows(),
      error = function(e) NULL
    )
  })
  
  output$plot <- renderPlot({
    req(plotData())
    plotData() %>% ggplot() + 
      geom_line(aes(x = X, y = Y, colour = as.factor(Scenario))) +
      theme(legend.title=element_blank())
  })
}

shinyApp(ui, server)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Function that inserts a space for every Nth character in a string isn't working the way I think it should?

Bad path not working how I think it should in C++ function

Python findall() not working like I think it should

I don't know why this is not printing the way I think it should

Why isn't my Where working as I think it should?

This CSS :is() Selector Isn't Working As I Think It Should

C Programming: fgets() function is not reading the values that I think it should

Vim auto wrap not working - the way I think it is supposed to

Date range not working properly, specifically the to, function I think

Chloropeth map in R not working out, I think the problem is in merging the data

Is there a way to make a wrapper function for renderUI in Shiny (R)?

I can't get pool.map or pool.starmap to work the way I think it should

I think MySqli select is not working?

C# - response.Content.ReadAsAsync<Result> not working as I think it should work

display: block on a nav bar (CSS) isn't working like I think it should....?

How does the utility "sort" work? (why does it not work the way I think it should?)

How does the linux utility "sort" work? (why does it not work the way I think it should?)

How should I think about the parameters of fread()?

python regex not behaving as i think it should

Tkinter program does not behave as I think it should

event not bubbling like I think it should

Two rectangles are not intersecting when I think they should

executing a function in R shiny after user text input not working

Why is my remove UI function in R shiny not working?

import random isn't working (I think)

I think my if else statement is not working

function str_slug is deprecated and not working, what should i do?

Can I copy the result of an output and use it in an R/Shiny function?

Regex not working way it should with .replace()