paulgovan / BayesianNetwork

Bayesian Network Modeling and Analysis
http://paulgovan.github.io/BayesianNetwork/
Apache License 2.0
119 stars 38 forks source link

Inference ShinyApp #10

Closed MayaGans closed 6 years ago

MayaGans commented 6 years ago

Hi! I absolutely LOVE the Shiny App you've made! It's incredibly inspiring and I want to fully understand it before applying something similar to my own data. This is my first go at a shiny app so I'm sorry if my questions are extremely obvious but it's hard to google some of these issues!

Specifically, I want to use a network I've already made and create what you have under the inference tab using that network.

I'm using the Alarm dataset in my example below, and rather than letting the event be specified I only want it to be "ACO2" (as seen in nodeProbs).

1) I can't seem to get the buttons to generate the alarm col names dynamically so I defined the choices as colnames(dat) in the Inputselect for input$evidenceNode where you have it as ""

2) Similarly, I can't generate the input$evidence drop down [I put choices = c("HIGH", "LOW", "NORMAL") but this isn't always the case so I'd like this to update dynamically]

3) When trying to debug I put specific arguments into nodeProbs but a graph still wont generate.

Again, I realize I'm asking a lot and I'm sorry in advanced if these questions are silly. Thank you for any help you can provide because the application you made is magnificent and I'm learning so much going through your code!

library(bnlearn)
library(shiny)
library(r2d3)
library(shinydashboard)

ui <- fluidPage(

  box(
    title = "Evidence",
    status = "success",
    width = NULL,
    helpText("Select evidence to add to the model:"),
    shiny::fluidRow(
      shiny::column(6,

                    # Evidence node input select
                    shiny::selectInput(
                      "evidenceNode", label = shiny::h5("Evidence Node:"),
                      colnames(dat)
                    )),
      shiny::column(6,

                    # Evidence input select
                    shiny::selectInput(
                      "evidence", label = shiny::h5("Evidence:"),
                      c("HIGH", "LOW", "NORMAL")
                    )
      )
    ),

    shiny::column(
      width = 8,

      # Event parameter box
      shinydashboard::box(
        title = "Event Parameter",
        status = "success",
        width = NULL,

        # Event conditional PD plot
        shiny::plotOutput("distPlot")
      )
  )
))

shinyServer(function(input, output, session) {

  output$text <- renderText({ 
    paste(input$evidenceNode)
  })

  data(alarm)
  # input the alarm data
  dat <- alarm

  # structure of the network
  modelstring = paste0("[HIST|LVF][CVP|LVV][PCWP|LVV][HYP][LVV|HYP:LVF][LVF]",
                       "[STKV|HYP:LVF][ERLO][HRBP|ERLO:HR][HREK|ERCA:HR][ERCA][HRSA|ERCA:HR][ANES]",
                       "[APL][TPR|APL][ECO2|ACO2:VLNG][KINK][MINV|INT:VLNG][FIO2][PVS|FIO2:VALV]",
                       "[SAO2|PVS:SHNT][PAP|PMB][PMB][SHNT|INT:PMB][INT][PRSS|INT:KINK:VTUB][DISC]",
                       "[MVS][VMCH|MVS][VTUB|DISC:VMCH][VLNG|INT:KINK:VTUB][VALV|INT:VLNG]",
                       "[ACO2|VALV][CCHL|ACO2:ANES:SAO2:TPR][HR|CCHL][CO|HR:STKV][BP|CO:TPR]")
  dag = model2network(modelstring)

fit <- bnlearn::bn.fit(dag, dat, method = "bayes", iss = 5)

# Send the evidence node choices to the user
# shiny::observe({
#  shiny::updateSelectInput(session, "evidenceNode", choices = names(dat()))
# })

# Send the evidence choices to the user
shiny::observe({
  whichNode <- which(colnames(dat()) == input$evidenceNode)
  evidenceLevels <- as.vector(unique(dat()[,whichNode]))
  shiny::updateSelectInput(session, "evidence", choices = evidenceLevels)
})

# Perform Bayesian inference based on evidence and plot results
output$distPlot <- shiny::renderPlot({
  if (is.null(dat()))
    return(NULL)
  if (all(sapply(dat, is.numeric)))
    shiny::validate(
      shiny::need(
        try(distPlot != ""),
        "Inference is currently not supported for continuous variables..."
      )
    )

  # Create a string of the selected evidence
  str1 <- paste0("(", input$evidenceNode, "=='", input$evidence, "')")

  # Estimate the conditional PD and tabularize the results
  nodeProbs <- prop.table(table(bnlearn::cpdist(fit(), "ACO2", eval(parse(text = str1)))))

  # Create a bar plot of the conditional PD
  barplot(
    nodeProbs,
    col = "lightblue",
    main = "Conditional Probabilities",
    border = NA,
    xlab = "Levels",
    ylab = "Probabilities",
    ylim = c(0, 1)
  )
})

})

shinyApp(ui = ui, server = server)
paulgovan commented 6 years ago

Hi Maya, glad you like the app. I'm a bit confused by your questions. Are you having trouble with this app or trying to create your own? If you're having trouble with dynamically sending inputs to the user, check out updateSelectInput (https://shiny.rstudio.com/reference/shiny/latest/updateSelectInput.html). There's an example that may help.

MayaGans commented 6 years ago

Sorry for the confusion - I was trying to build your app from scratch to reproduce only the Inference tab but instead I took the more logical direction of dissecting your code line for line.

I see another issue was opened to the same effect but I'm hoping to reproduce the Inference tab but with the ability to select multiple evidence nodes (and multiple drop downs for the evidence).

Thank you for the wonderful app!