Isolate versus reactive in shiny

I am creating a simple, brilliant application for displaying centralization indicators in a network selected by a user. The user selects a network format, a network file and a measure of centralization for calculation, and then clicks a button on the layout and visualizes a graph where the size of the nodes is proportional to the centrality node. At the output, renderPlotI isolated all the inputs except the button, so that the calculation is performed only when the user has selected the appropriate information (format, file, measure) and presses the visualization button. It works, but with the following problem: every time the visualization button is clicked, the layout is reviewed, and the network is rendered differently. I would like to avoid this behavior. I tried to include layout calculation in a callreactive(see Comment), but then the isolation failed. Therefore, I can isolate , but not make the code reactive, or make it reactive without isolation.

The following is the user interface code:

shinyUI(fluidPage(
titlePanel("Visualize and compare centrality measures"),

sidebarLayout(
  sidebarPanel(

  selectInput("format", label = h4("Select graph format"), 
              choices = c("gml", "graphml", "edgelist", "pajek", "ncol", "lgl",
                          "dimacs", "graphdb", "dl")),

  br(),

  fileInput("graph", label = h4("Load graph")),

  br(),


  selectInput("centrality", label = h4("Select centrality measure"), 
              choices = c("degree", "eigenvector", "Katz")),

  br(),

  conditionalPanel(
    condition = "input.centrality == 'Katz'",
    numericInput("alpha", 
                 label = h4("Alpha"), min=0, step = 0.05, 
                 value = 1)),


  actionButton("plot", "Visualize")


  ),
mainPanel(plotOutput("net"))
)
))

Below is the server code:

library(igraph)
# mapping k from [x,y] in [w,z] with f(k) = w + (z-w) * (k-x)/(y-x)
map = function(k,x,y,w,z) {if (x != y) w + (z-w) * (k-x)/(y-x) else (w+z)/2}

shinyServer(
function(input, output) {

# read input graph
# g = reactive({read.graph(file=input$graph$datapath, format=input$format)});
# compute layout
# coords = reactive({layout.fruchterman.reingold(g)});

output$net = renderPlot({
  if (input$plot > 0) {
    g = isolate(read.graph(file=input$graph$datapath, format=input$format))
    coords = layout.fruchterman.reingold(g)

    cent = isolate(switch(input$centrality, 
                  "degree" = degree(g),
                  "eigenvector" = evcent(g)$vector,
                  "Katz" = alpha.centrality(g, alpha = input$alpha)))

    plot(g, layout=coords, vertex.label=NA, vertex.size = map(cent, min(cent), max(cent), 1, 10))

  }


})
} 
)
+4
source share
1 answer

My answer (thanks to Nicholas):

UI.R

shinyUI(fluidPage(
titlePanel("Visualize and compare centrality measures"),

sidebarLayout(
sidebarPanel(

  selectInput("format", label = h4("Graph format"), 
              choices = c("gml", "graphml", "edgelist", "pajek", "ncol", "lgl",
                          "dimacs", "graphdb", "dl")),

  br(),

  fileInput("graph", label = h4("Graph file")),

  br(),


  selectInput("centrality", label = h4("Centrality measure"), 
              choices = c("degree", "eigenvector", "Katz", "pagerank")),

  br(),

  conditionalPanel(
    condition = "input.centrality == 'Katz' || input.centrality == 'pagerank'",
    numericInput("alpha", 
                 label = h4("Damping"), min=0, max = 1, step = 0.05, 
                 value = 0.85), br()),


  actionButton("plot", "Visualize")


  ),
mainPanel(plotOutput("net"))
)
))

Server.R

library(igraph)
map = function(k,x,y,w,z) {if (abs(x - y) > 10^-3) w + (z-w) * (k-x)/(y-x) else (w+z)/2}

shinyServer(
function(input, output) {

# read and cache the graph
inputGraph = reactive({
  inFile = input$graph
  if (!is.null(inFile))
    read.graph(file=inFile$datapath, format=input$format)
})

# read and cache the layout
inputCoords = reactive({layout.fruchterman.reingold(inputGraph())});

# render the plot
output$net = renderPlot({
  # viualize button
  input$plot
  # isolate input graph
  g = isolate(inputGraph())

  if (!is.null(g)) {      
    coords = isolate(inputCoords())
    cent = isolate(switch(input$centrality, 
                  "degree" = degree(g),
                  "eigenvector" = evcent(g)$vector,
                  "Katz" = alpha.centrality(g, alpha = input$alpha),
                  "pagerank" = page.rank(g, damping = input$alpha)$vector))

    top = which.max(cent)
    V(g)$color = "skyblue"
    V(g)[top]$color = "red"

    plot(g, layout=coords, vertex.label=NA, vertex.size = map(cent, min(cent), max(cent), 1, 10))
  }      
})
}
)
+1
source

All Articles