Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

isolate vs reactive in shiny

Tags:

r

shiny

I am building a simple shiny app to display centrality measures on a network chosen by the user. The user chooses the network format, the file of the network, and the centrality measure to compute, and then clicks a button to layout and visualize the graph where size of nodes is proportional to node's centrality. In the renderPlot output I isolated all the inputs but the button, so that the computation is done only when the user has chosen the relevant information (format, file, measure) and clicks the visualize button. It works but with the following problem: each time the visualize button is clicked, the layout is recomputed and the network is visualized in a different way. I would like to avoid this behaviour. I tried to include the layout computation in a reactive call (see commented code), but then the isolation fails. Hence I am able to isolate but not make the code reactive, or to make it reactive without isolation.

The UI code follows:

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"))
)
))

The server code follows:

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))

  }


})
} 
)
like image 411
Massimo Franceschet Avatar asked Nov 09 '22 22:11

Massimo Franceschet


1 Answers

My answer (thanks to Nicola as well):

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))
  }      
})
}
)
like image 84
Massimo Franceschet Avatar answered Nov 15 '22 07:11

Massimo Franceschet