微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

R Shiny 中的反应式桑基图,以多个数据帧作为输入

如何解决R Shiny 中的反应式桑基图,以多个数据帧作为输入

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

我的代码:(在 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,20,4,5))
level_3 <- as.data.frame(matrix(sample(seq(0,25,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)

我认为创建所有数据帧的列表()、级别可能会有所帮助,但这不起作用。我收到此错误

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

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

提前致谢!

解决方法

如果您想访问服务器中的任何 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 包。

反应性的概念很棘手,但如果您不熟悉 shinychapter 3 of Mastering Shiny 应该很​​有启发性。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。