0

I know this question has come up a few times e.g. Markov Model diagram directly from data (makovchain or deemod package?). I attempted to implement remedies based on those solutions, but this is still not working. Clearly, I am missing something and would be grateful for any assistance!

In short, I am trying to supply state_names to heemod::define_transition within a Shiny app.

Here is my code:


library(heemod)
library(diagram)
library(shiny)

ui=shinyUI(fluidPage(
  titlePanel("Markov Diagram Creator"),
  fluidRow(
    sidebarPanel(
      textAreaInput("statenames_1",label = "Enter state names here...", value = "H,S1,S2,D"),
      actionButton("go","Go")
    ),
    
    mainPanel(
      
      hr(),
      plotOutput("plot")
      
    )
  )))

server=function(input,output){
  
  state_names <- reactive( {
    unlist(strsplit(x=input$statenames_1,split = "[[:punct:]]"))
  })
  
  len_states <- reactive({length(state_names())}) 
  states <- reactive({state_names()})
  statenames <- reactive({list(states(), states())})
  markovTransitionMatrix <- reactive({matrix(0.25, nrow = len_states(), ncol = len_states(), dimnames = statenames())})
  
  lis <- reactive({ as.list( markovTransitionMatrix() ) })
  lis()$state_names  <-  reactive({ statenames() }) # Error in lis() <- reactive({ : invalid (NULL) left side of assignment
  
  output$plot <- renderPlot({
    plot(do.call( define_transition,  lis() ), cex=0.75, ylim = c(0,.4))
    
  })
  
  
}

shinyApp(ui,server)
  • I have renamed the ```statenames``` ID to ```statenames_1``` in the ```textAreaInput```. Also uncommented the offending line to recreate the error. – Grant Coble-Neal Aug 17 '20 at 01:48
  • I'd probably do `lis2 <- reactive({ z <- list(); z$state_names <- statenames(); z; })` and depend on `lis2()` from there on out. – r2evans Aug 17 '20 at 02:42
  • Or just fix it in the original `lis()` assignment. – r2evans Aug 17 '20 at 02:42

1 Answers1

1

Without testing, I think this will address your need:

  lis <- reactive({
    out <- as.list( markovTransitionMatrix() )
    out$state_names <- statenames()
    out
  })
  # delete:   lis()$state_names  <-  reactive({ statenames() })

The rationale is that in general (and shiny is no different), there really isn't a way to assign a property ($state_names) to a function call (lis()). There are some functions in R that look like you're assigning to a function (e.g., names(z) <- c("a","b")), but those are special functions, and that nomenclature/syntax does not apply to shiny reactive variables.

As a side note, while on one side I see many shiny reactive blocks that try to do too much in them, I wonder if some of your reactive blocks are taking "too-small steps". For instance,

  ### no longer needed ---v
  # len_states <-
  # states <-
  # statenames <-
  # markovTransitionMatrix <-
  ### no longer needed ---^
  lis <- reactive({
    states <- state_names()
    statenames <- list(states, states)
    mTM <- as.list(matrix(0.25, nrow = length(states), ncol = length(states), dimnames = statenames))
    mTM$state_names <- statenames
    mTM
  })

This is likely bordering on swinging too far the other way, but some of your reactive blocks are ... rather trivial, and if one of the initial/smaller ones are only ever depended on by the next on in the chain, then breaking them out has little benefit and possibly a minute (!) performance impact. (Okay, really minute ... the point is don't do busy-work in reactivity if you don't need to.)

r2evans
  • 141,215
  • 6
  • 77
  • 149