christophergandrud / networkD3

D3 JavaScript Network Graphs from R
http://christophergandrud.github.io/networkD3
650 stars 269 forks source link

chordNetwork doesn't refresh with new data in Shiny app #207

Open hetmanb opened 7 years ago

hetmanb commented 7 years ago

Hi!

Really enjoying the visualizations provided in the networkD3 package. I've been struggling a bit with the chordNetwork function, however. It seems as though when I use the function and try to change the input data, rather than refreshing and redrawing the chord diagram, a new one is simply drawn overtop of the existing one.

Taking a look at the original D3 chord diagram code, the svg element seems to be first declared, the content removed, then the chord is built ontop. However, in the current iteration, the line for removing the existing svg element is missing.

E.g. (old iteration)

var arc = d3.svg.arc()
.innerRadius(r0)
.outerRadius(r0 + 20);
// declaring the svg element then removing the content? 
var svg = d3.select(el).select('#svg1');
svg.remove();
$(el).html('');

I've included a minimal working example below - if you change the slider input, the chord diagram is redrawn on top of the old one, instead of 'refreshing.'

library(shiny)
library(networkD3)
library(reshape2)
shinyApp(
  ui = fillPage(
    fillCol(flex = c(NA, 1), 
      inputPanel(
        sliderInput("chord_range1", label = "Thresholds for chordplot", min = 0, max = 1, value = c(0.7,0.95), dragRange = T)

      ),
      networkD3::chordNetworkOutput('sourceChord',
                                    height = "100%"
                                    )
    )
  ),
  server = function(input, output) {

    # Create input data, similarity matrix with self-self = 1.00
    mat <- matrix(runif(100, 0, 1), ncol = 10)
    mat <- mat %*% t(mat)
    mat <- as.matrix(dist(mat, upper = T, diag = T))
    mat <- mat / max(mat)
    mat <- 1 - mat

    # reactive expression to filter matrix based on input thresholds
    inFile <- reactive({
      inFile <- melt(mat)
      inFile <- subset(inFile, inFile$value > input$chord_range1[1] & inFile$value < input$chord_range1[2])
      inFile <- reshape2::dcast(inFile, Var1 ~ Var2)
      row.names(inFile) <- inFile[,1]
      inFile <- inFile[,-1]
    })

    #draw chord network
    output$sourceChord <- renderchordNetwork({

      chordNetwork(inFile(),
               labels = colnames(inFile()),
               fontSize = 10,
               padding = 0.03,
               labelDistance = 50,
               width = 800, 
               height = 800
               )
      })
    },

  options = list(height = 800)
)

Thanks!

cjyetman commented 7 years ago

Thanks for the reproducible example... I can verify that I see the same problem. Personally, I won't be able to look into this any time real soon, but maybe someone else will jump in.