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))
}
})
}
)
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))
}
})
}
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With