I am rendering a chord network in a Shiny app. What I would like to do is provide two different representations of the network. One based on who is influenced by whom, the other based on who influences whom. In a nutshell what I am representing is a dataset in one version, and the transpose of that dataset in another version.
My problem is that when I render the network and toggle the input, the new version of the plot is simply laid over the old version of the plot. I need to somehow erase the previous plot before displaying the next plot.
This minimal example shows the default presentation:
This is what happens when I choose to plot the transposed data (i.e. I change the dataset)
If I switch back to the original choice, it simply overlays again.
I am sure there is a simple answer to this problem, I just haven't been able to google the right words.
Minimal reproducible code below
library(shiny)
library(networkD3)
Data <- matrix(c(NA, 1951, 8010, 1013,
5871, NA, 16145, 990,
8916, 2060, NA, 940,
2868, 6171, 8045, NA), nrow = 4)
ui <- fluidPage(
titlePanel("Chord network"),
mainPanel( htmlOutput("inputDataChoice"),
chordNetworkOutput(outputId = "chord_network", width = "600px", height = "600px")
)
)
server <- function(input, output) {
#Choose the data type
output$inputDataChoice <- renderUI({
selectInput(inputId = "dataChoice", label = "Choose data shape",
choices=c("Influenced", "Influences"),
width = "450px"
)})
#Dataset shape based on choice
chordData <- reactive({
switch(input$dataChoice,
"Influenced" = Data,
"Influences" = t(Data))
})
#Plot
observe ({
output$chord_network <- renderchordNetwork({
chordNetwork(chordData(),
padding = 0.1,
colourScale = c("#000000",
"#FFDD89",
"#957244",
"#F26223"),
labels = c("Bob", "Brenda", "Barry", "Belinda"))
})})
}
shinyApp(ui = ui, server = server)
Interesting bug! It looks like the issue is actually in the package being used. I'm surprised this bug hasn't been reported, I guess people are not using is much on shiny?!
I fixed the bug by clearing the canvas before rendering the widget. I'm not a d3 expert but I think this can be fixed in the package chordNetwork.js
by using data().enter()
instead of datum()
but unfortunately I couldn't get this working.
Instead, it's fixed by inserting the following line of code before we render any plot.
d3.select(el).select("g").selectAll("g").remove() //Create a blank canvas
You can access this fixed package in my forked repository here,https://github.com/sada1993/networkD3. Use devtools::install_github("sada1993/networkD3")
to install the package.
Perhaps we could add a PR for this fix? But it looks like the package is no longer under development.
Here is the diff to see the changes: https://github.com/christophergandrud/networkD3/compare/master...sada1993:master