【问题标题】:Reactive Sankey Diagram in R Shiny with multiple dataframes as inputR Shiny中的反应式桑基图,具有多个数据帧作为输入
【发布时间】:2021-07-29 13:09:56
【问题描述】:

这是我第一次创建仪表板,我遇到了一个我似乎无法解决的问题。我创建了一个 sankey 图,我希望能够通过不同的数据框(在本例中:level_1、level_2、level_3)以交互方式更改其内容。我只用常规图练习过这个,其中输入来自一个数据框中的变量,这是我在这段代码中的起点(例如,我有一个 df$country,所以我在我的plot --> 然后我可以在仪表板侧边栏中选择不同的国家,以更改情节的内容)。当输入必须来自单独的数据帧时,我不知道该怎么做。

我的代码:(在 app.R 中)

level_1 <- as.data.frame(matrix(sample(seq(0,40), 15, replace=T ), 3, 5))
level_2 <- as.data.frame(matrix(sample(seq(0,40), 20, replace=T ), 4, 5))
level_3 <- as.data.frame(matrix(sample(seq(0,40), 25, replace=T ), 5, 5))

levels <- list(level_1, level_2, level_3)

ui <- dashboardPage(
    dashboardHeader(title = "title"),
    
    dashboardSidebar(
        selectInput("in_levels", "Levels", choices = levels) 

        
    ),
    dashboardBody(
        fluidRow(sankeyNetworkOutput("widget1"))
    )
)

server <- function(input, output) { 
    
    links <- input$in_levels %>%
        rownames_to_column(var="source") %>% 
        gather(key="target", value="value", -1) %>%
        filter(value != 0)
    
    nodes <- data.frame(
        name=c(as.character(links$source), as.character(links$target)) %>% 
            unique()
    )
    
    links$IDsource <- match(links$source, nodes$name)-1 
    links$IDtarget <- match(links$target, nodes$name)-1
    
    output$widget1 <- renderSankeyNetwork({
        sankeyNetwork(Links = links, Nodes = nodes,
                      Source = "IDsource", Target = "IDtarget",
                      Value = "value", NodeID = "name", fontSize = 14, nodeWidth = 60,
                      fontFamily = "Arial", iterations = 0, sinksRight=TRUE)
    })
}

shinyApp(ui, server)

我认为创建所有数据框的 list()、levels 可能会有所帮助,但这不起作用。我收到此错误:

Error : Can't access reactive value 'in_levels' outside of reactive consumer.
i Do you need to wrap inside reactive() or observer()?

我搜索了 reactive() 和 observer() 以尝试找出我的下一步应该是什么,但我还没有找到解决方案。如果有人可以就如何进行、进行更改或阅读一些内容以增加我的理解提供建议,我将不胜感激。

提前致谢!

【问题讨论】:

  • 您不能在selectInputchoices 参数中使用数据帧列表。您可以先执行levels &lt;- list(data1=level_1, data2=level_2, data3=level_3),然后执行choices = c("data1", "data2", "data3"),然后在server 中使用levels[[input$in_levels]] 获得选定的数据框。
  • 谢谢@StéphaneLaurent,这非常有帮助!

标签: r shiny shinydashboard shiny-reactivity


【解决方案1】:

如果您想访问服务器中的任何 input 值,您需要使用响应式上下文。 shiny 不允许您这样做,但即使这样做,如果更新了 input 值,服务器端代码也不会更新以反映更改。由于您希望 linksnodes 都是动态的并且相互依赖,因此一个巧妙的解决方案可能是将这两个对象存储在一个列表中,如下所示:

server <- function(input, output) { 
    
    plot_data <- reactive({

      # Perform all your computation inside this reactive!    

      links <- input$in_levels %>%
        rownames_to_column(var="source") %>% 
        gather(key="target", value="value", -1) %>%
        filter(value != 0)
    
      nodes <- data.frame(
        name = c(as.character(links$source), as.character(links$target)) %>% 
            unique()
      )
    
      links$IDsource <- match(links$source, nodes$name)-1 
      links$IDtarget <- match(links$target, nodes$name)-1

      # Return the data in a list
      list(links = links, nodes = nodes)

    })
    
    # Access the datasets by calling the reactive and then treating as a normal list
    output$widget1 <- renderSankeyNetwork({
        sankeyNetwork(Links = plot_data()$links, Nodes = plot_data()$nodes,
                      Source = "IDsource", Target = "IDtarget",
                      Value = "value", NodeID = "name", fontSize = 14, nodeWidth = 60,
                      fontFamily = "Arial", iterations = 0, sinksRight=TRUE)
    })
}

这是未经测试的,因为我当前的 R 版本不支持 network3d 包。

反应性的概念很棘手,但如果您是 shiny 的新手,chapter 3 of Mastering Shiny 应该会很有启发性。

【讨论】:

  • 谢谢!我想我现在了解 reactive() 的工作原理。应用您的代码似乎确实有效(运行时没有错误),但我的其余代码仍然存在问题(我得到一个空仪表板)。我认为问题在于 levels 列表的结构:我在仪表板之前创建了 sankey 图,每个级别都有一个 df。因此,我的 links 代码针对数据框(例如,因为使用 rownames_to_column),但现在我使用的是内部带有数据框的 list()。知道如何解决这个问题吗?
  • 我认为这不会导致您的问题,例如plot_data()$links 将返回一个 data.frame 而不是一个列表。我认为这个问题很可能是因为您不应该使用 data.frames 列表作为selectInput()choices 参数。见Stéphane Laurent上面的评论。
猜你喜欢
  • 1970-01-01
  • 2014-06-16
  • 1970-01-01
  • 2020-11-20
  • 2019-09-08
  • 2016-10-15
  • 2021-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多