Reactive height for sankeyNetworkOutput from networkD3

梦想的初衷 提交于 2019-12-11 10:59:36

问题


I have a Shiny dashboard that is displaying a sankeyNetwork from the networkD3 package. I'm creating the sankeyNetwork inside of a renderSankeyNetwork function on the server and then calling it on the ui with sankeyNetworkOutput. I'd like to make the height of the created sankeynetwork be dependent on a height value I've created.

I tried using renderUI with uiOutput to run the sankeyNetworkOutput on the server, but it doesn't seem to be working. The dashboard works otherwise but there is nothing where the sankeynetwork is supposed to be. I belive this is likely to do with the fact uiOutput doens't work well with renderSankeyNetwork.

Below is two chunks of code, both should be a proper reprex. The first shows how the dashboard works without having a dynamic height. The latter is my attempt to use renderUI+uiOutput. I looked into a few other ideas for how to do it but didn't have any luck finding anything useful.

Any ideas? Thanks in advance.

Working version:

library(shiny)

ui <- fluidPage(
    selectInput(inputId = "plot",
                label   = "plot",
                choices = c("plota", "plotb")),

    sankeyNetworkOutput("diagram")
    # uiOutput("diagram")
)

server <- function(input, output) {

    dat <- data.frame(plot   = c("plota", "plota", "plotb", "plotb", "plotb"),
                      start  = c("a", "b", "a", "b", "c"),
                      finish = c("x", "x", "y", "y", "z"),
                      count  = c(12, 4, 5, 80, 10),
                      height = c("200px", "200px", "400px", "400px", "400px"))

    temp_dat <- reactive({
        filter(dat, plot == input$plot)
    })

    links <- reactive({
        temp_dat <- temp_dat()
        data.frame(source = temp_dat$start,
                   target = temp_dat$finish,
                   value  = temp_dat$count)
    })

    nodes <- reactive({
        temp_links_1 <- links()
        data.frame(name = c(as.character(temp_links_1$source),
                            as.character(temp_links_1$target))#,
        ) %>%
            unique()
    })

    links2 <- reactive({
        temp_links <- links()
        temp_nodes <- nodes()
        temp_links$IDsource <- match(temp_links$source, temp_nodes$name) - 1
        temp_links$IDtarget <- match(temp_links$target, temp_nodes$name) - 1
        temp_links
    })

    output$diagram <- renderSankeyNetwork({
        sankeyNetwork(
            Links       = links2(),
            Nodes       = nodes(),
            Source      = "IDsource",
            Target      = "IDtarget",
            Value       = "value",
            NodeID      = "name",
            sinksRight  = FALSE,
            fontSize    = 13
        )
    })

    # output$diagram <- renderUI({
    #     temp <- temp_dat()
    #     sankeyNetworkOutput("diagram", height = c(unique(temp$height)[1]))
    # })

}

shinyApp(ui = ui, server = server)

renderUI + uiOutput version:

library(shiny)

ui <- fluidPage(
    selectInput(inputId = "plot",
                label   = "plot",
                choices = c("plota", "plotb")),

    # sankeyNetworkOutput("diagram")
    uiOutput("diagram")
)

server <- function(input, output) {

    dat <- data.frame(plot   = c("plota", "plota", "plotb", "plotb", "plotb"),
                      start  = c("a", "b", "a", "b", "c"),
                      finish = c("x", "x", "y", "y", "z"),
                      count  = c(12, 4, 5, 80, 10),
                      height = c("200px", "200px", "400px", "400px", "400px"))

    temp_dat <- reactive({
        filter(dat, plot == input$plot)
    })

    links <- reactive({
        temp_dat <- temp_dat()
        data.frame(source = temp_dat$start,
                   target = temp_dat$finish,
                   value  = temp_dat$count)
    })

    nodes <- reactive({
        temp_links_1 <- links()
        data.frame(name = c(as.character(temp_links_1$source),
                            as.character(temp_links_1$target))#,
        ) %>%
            unique()
    })

    links2 <- reactive({
        temp_links <- links()
        temp_nodes <- nodes()
        temp_links$IDsource <- match(temp_links$source, temp_nodes$name) - 1
        temp_links$IDtarget <- match(temp_links$target, temp_nodes$name) - 1
        temp_links
    })

    # output$diagram <- renderSankeyNetwork({
    #     sankeyNetwork(
    #         Links       = links2(),
    #         Nodes       = nodes(),
    #         Source      = "IDsource",
    #         Target      = "IDtarget",
    #         Value       = "value",
    #         NodeID      = "name",
    #         sinksRight  = FALSE,
    #         fontSize    = 13
    #     )
    # })

    output$diagram <- renderUI({
        temp <- temp_dat()
        sankeyNetworkOutput("diagram", height = c(unique(temp$height)[1]))
    })

}

shinyApp(ui = ui, server = server)

回答1:


You were almost there:

You'll have to define separate output names for your network and the renderUI output and you have to provide the height argument as character:

library(shiny)
library(networkD3)
library(dplyr)

ui <- fluidPage(
  selectInput(inputId = "plot",
              label   = "plot",
              choices = c("plota", "plotb")),
  # sankeyNetworkOutput("diagram")
  uiOutput("diagram")
)

server <- function(input, output) {

  dat <- data.frame(plot   = c("plota", "plota", "plotb", "plotb", "plotb"),
                    start  = c("a", "b", "a", "b", "c"),
                    finish = c("x", "x", "y", "y", "z"),
                    count  = c(12, 4, 5, 80, 10),
                    height = c("200px", "200px", "400px", "400px", "400px"))

  temp_dat <- reactive({
    filter(dat, plot == input$plot)
  })

  links <- reactive({
    temp_dat <- req(temp_dat())
    data.frame(source = temp_dat$start,
               target = temp_dat$finish,
               value  = temp_dat$count)
  })

  nodes <- reactive({
    temp_links_1 <- req(links())
    data.frame(name = c(as.character(temp_links_1$source),
                        as.character(temp_links_1$target))#,
    ) %>%
      unique()
  })

  links2 <- reactive({
    temp_links <- req(links())
    temp_nodes <- req(nodes())
    temp_links$IDsource <- match(temp_links$source, temp_nodes$name) - 1
    temp_links$IDtarget <- match(temp_links$target, temp_nodes$name) - 1
    temp_links
  })

  output$mySankeyNetwork <- renderSankeyNetwork({
    sankeyNetwork(
      Links       = links2(),
      Nodes       = nodes(),
      Source      = "IDsource",
      Target      = "IDtarget",
      Value       = "value",
      NodeID      = "name",
      sinksRight  = FALSE,
      fontSize    = 13
    )
  })

  output$diagram <- renderUI({
      temp <- temp_dat()
      sankeyNetworkOutput("mySankeyNetwork", height = as.character(unique(temp$height)[1]))
  })

}

shinyApp(ui = ui, server = server)


来源:https://stackoverflow.com/questions/58208904/reactive-height-for-sankeynetworkoutput-from-networkd3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!