简体   繁体   English

在模块化 shiny 应用程序中显示基于两个不同数据帧的两个可视化

[英]Display two visualizations that are based on two different dataframes in modularized shiny app

In the modularized shiny app below I want to create one map which is created and one plot below the map.在下面的模块化 shiny 应用程序中,我想创建一个已创建的 map 和一个 plot 在 Z1D78DC8ED51214490AEZ8 下方。 The 2 visualizations are based on 2 different dataframes though and I do not know exactly how display them both.虽然这 2 个可视化基于 2 个不同的数据框,但我不知道如何显示它们。

library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(leaflet)
library(dplyr)
library(plotly)
# Some data
data<-structure(list(scientificName = c("Turdus merula Linnaeus, 1758", 
                                        "Passer domesticus (Linnaeus, 1758)", "Cantharellus cinereus (Pers.) Fr.", 
                                        "Flammulina fennae Bas", "Mycena crocata (Schrad.) P.Kumm.", 
                                        "Lepista luscina (Fr.) Singer", "Mycena permixta (Britzelm.) Sacc.", 
                                        "Rhodophyllus byssisedus (Pers.) Quel.", "Rhodophyllus porphyrophaeus (Fr.) J.E.Lange", 
                                        "Panaeolus rickenii Hora"), decimalLatitude = c(52.204429, 51.387818, 
                                                                                        52.176667, 50.066111, 49.179167, 49.419444, 52.3, 52.3, 49.419444, 
                                                                                        49.179167), decimalLongitude = c(21.189275, 19.62673, 19.088056, 
                                                                                                                         19.502778, 22.434722, 20.380556, 20.566667, 20.566667, 20.380556, 
                                                                                                                         22.434722)), row.names = c(1L, 2L, 32L, 35L, 37L, 38L, 39L, 40L, 
                                                                                                                                                    41L, 42L), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
                                                                                                                                                    ))
data$year<-c(1990,1989,2003,1990,1980,1990,1989,2003,1990,1980)
# Define the side panel UI and server
sideUI <- function(id) {
  ns <- NS(id)
  tagList(
    
    uiOutput(ns("ye")),
    uiOutput(ns("scient")),
    actionButton(ns("action"),"Submit")
  )
  
}

sideServer <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      
      # define a reactive and return it
      react<-eventReactive(input$action,{
        
        omited <-subset(data, data$scientificName %in% isolate(input$sci))
      })
      
      output$ye<-renderUI({
        pickerInput(
          inputId = session$ns("yea"),
          label = "Year", 
          choices = sort(unique(data$year),decreasing=F),
          selected = unique(data$year),
          multiple = T
          
        )
      })
      
      output$scient<-renderUI({
        data <-subset(data, data$year %in% input$yea)
        
        pickerInput(
          inputId = session$ns("sci"),
          label = "Scientific name", 
          choices = unique(data$scientificName),
          selected = unique(data$scientificName)[1], 
          
        )
      })
      
      return(react)
      counted<-reactive({data.frame(react() %>% 
                                      group_by(year) %>% 
                                      summarise(count=n()
                                      ))
      })
      return(counted)
    })
}
# In this case this server not needed but using uiOuput/renderUI in real case
# sideServer <- function(id) { moduleServer(id,function(input, output, session) { })}

# Define the UI and server functions for the map
mapUI <- function(id) {
  ns <- NS(id)
  tagList(
    leafletOutput(ns("map")),
    plotlyOutput(ns("plot"))
  )
}

mapServer <- function(id, city) {
  moduleServer(
    id,
    function(input, output, session) {
      output$map<-renderLeaflet({
        
        leaflet(data = city()) %>% addTiles() %>%
          addMarkers(~decimalLatitude, ~decimalLongitude, popup = ~as.character(scientificName), label = ~as.character(scientificName))
      })
    })
}
plotServer <- function(id, city) {
  moduleServer(
    id,
    function(input, output, session) {
      output$plot<-renderPlotly({
        
        fig <- plot_ly(data=city(), x = ~as.factor(year), y = ~count, type = 'scatter', mode = 'lines')
        
        fig%>% layout(title = paste("Count of",input$sci ,"through the years"),
                      xaxis = list(title = "Years",tickangle=45),
                      yaxis = list (title = "Count"))
      })
    })
}
# Build ui & server and then run
ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(sideUI("side")),
  dashboardBody(mapUI("mapUK"))
)
server <- function(input, output, session) {
  
  # use the reactive in another module
  city_input <- sideServer("side")
  mapServer("mapUK", city_input)
  plotServer("plotPl",city_input)
  
}
shinyApp(ui, server)
  1. You have plotlyOutput(ns("plot")) in different module than server where is output$plot<-renderPlotly({ (the latter is in plotServer while ui output is in mapUI ). I decided to make new ui for plotServer , but you can also try to move elements from plotServer into mapServer .您在与server不同的模块中有plotlyOutput(ns("plot")) ,其中output$plot<-renderPlotly({ (后者在plotServer中,而 ui output 在mapUI中)。我决定为plotServer制作新的ui ,但是您还可以尝试将元素从plotServer移动到mapServer
  2. As you said, the problem is with returning multiple elements.正如您所说,问题在于返回多个元素。 But not just two dataframes, also some input.但不仅仅是两个数据框,还有一些输入。 To return more than one element, you need to create list, say like this: return(list(element1 = _object_to_return1, element2 = _object_to_return2)) .要返回多个元素,您需要创建列表,如下所示: return(list(element1 = _object_to_return1, element2 = _object_to_return2))
  3. I said above "return some input", that's because here: fig%>% layout(title = paste("Count of",input$sci,"through the years") you are using input, but input from different module. As you already know, you do not have direct access to objects from different modules and the same is with input s. That means you need to return input as well, but input needs to be wrapped into reactive() function. In your case, when there is module with two return s function, it should be one and look like this: return(list(react = react, counted = counted, sci = reactive(input$sci))) .我上面说“返回一些输入”,那是因为这里: fig%>% layout(title = paste("Count of",input$sci,"through the years")您正在使用输入,但输入来自不同的模块。如您已经知道,您无法直接访问来自不同模块的对象, input s 也是如此。这意味着您也需要返回input ,但input需要包装到reactive() function。在您的情况下,当有一个模块有两个return s function,它应该是一个,看起来像这样: return(list(react = react, counted = counted, sci = reactive(input$sci)))
  4. Now, because you have returned list, you need to access elements inside this list as normal elements from list, so when you pass arguments to function, it won't be react as previously, but city_input$react .现在,因为您已返回列表,您需要将此列表中的元素作为列表中的普通元素访问,因此当您将 arguments 传递给 function 时,它不会像以前那样react ,而是city_input$react You also need to add parameters to the server function - not just city , but also parameter for counted dataframe and input .您还需要将参数添加到服务器 function - 不仅是city ,还需要counted dataframe 的参数并input
  5. In case it won't be obvious for you - to access input from other module (after passing as argument) you access it as a normal function, so below you can see that I use sci() instead of input$sci万一这对你来说不是很明显 - 要访问来自其他模块的输入(作为参数传递后)你可以像普通的 function 一样访问它,所以在下面你可以看到我使用sci()而不是input$sci

Here is full code:这是完整的代码:

library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(leaflet)
library(dplyr)
library(plotly)
# Some data
data<-structure(list(scientificName = c("Turdus merula Linnaeus, 1758", 
                                        "Passer domesticus (Linnaeus, 1758)", "Cantharellus cinereus (Pers.) Fr.", 
                                        "Flammulina fennae Bas", "Mycena crocata (Schrad.) P.Kumm.", 
                                        "Lepista luscina (Fr.) Singer", "Mycena permixta (Britzelm.) Sacc.", 
                                        "Rhodophyllus byssisedus (Pers.) Quel.", "Rhodophyllus porphyrophaeus (Fr.) J.E.Lange", 
                                        "Panaeolus rickenii Hora"), decimalLatitude = c(52.204429, 51.387818, 
                                                                                        52.176667, 50.066111, 49.179167, 49.419444, 52.3, 52.3, 49.419444, 
                                                                                        49.179167), decimalLongitude = c(21.189275, 19.62673, 19.088056, 
                                                                                                                         19.502778, 22.434722, 20.380556, 20.566667, 20.566667, 20.380556, 
                                                                                                                         22.434722)), row.names = c(1L, 2L, 32L, 35L, 37L, 38L, 39L, 40L, 
                                                                                                                                                    41L, 42L), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
                                                                                                                                                    ))
data$year<-c(1990,1989,2003,1990,1980,1990,1989,2003,1990,1980)
# Define the side panel UI and server
sideUI <- function(id) {
  ns <- NS(id)
  tagList(
    
    uiOutput(ns("ye")),
    uiOutput(ns("scient")),
    actionButton(ns("action"),"Submit")
  )
  
}

sideServer <- function(id) {
  moduleServer(
    id,
    function(input, output, session) {
      
      # define a reactive and return it
      react<-eventReactive(input$action,{
        
        omited <-subset(data, data$scientificName %in% isolate(input$sci))
      })
      
      output$ye<-renderUI({
        pickerInput(
          inputId = session$ns("yea"),
          label = "Year", 
          choices = sort(unique(data$year),decreasing=F),
          selected = unique(data$year),
          multiple = T
          
        )
      })
      
      output$scient<-renderUI({
        data <-subset(data, data$year %in% input$yea)
        
        pickerInput(
          inputId = session$ns("sci"),
          label = "Scientific name", 
          choices = unique(data$scientificName),
          selected = unique(data$scientificName)[1], 
          
        )
      })
      
      counted<-reactive({react() %>% 
                                      group_by(year) %>% 
                                      summarise(count=n()
                                      )
        
      })
      return(list(react = react, counted = counted, sci = reactive(input$sci)))
    })
}
# In this case this server not needed but using uiOuput/renderUI in real case
# sideServer <- function(id) { moduleServer(id,function(input, output, session) { })}

# Define the UI and server functions for the map
mapUI <- function(id) {
  ns <- NS(id)
  tagList(
    leafletOutput(ns("map"))
  )
}

mapServer <- function(id, city) {
  moduleServer(
    id,
    function(input, output, session) {
      output$map<-renderLeaflet({
        
        leaflet(data = city()) %>% addTiles() %>%
          addMarkers(~decimalLatitude, ~decimalLongitude, popup = ~as.character(scientificName), label = ~as.character(scientificName))
      })
    })
}

plotUI <- function(id) {
  ns <- NS(id)
  
  tagList(
    plotlyOutput(ns("plot"))
  )
}

plotServer <- function(id, city, sci) {
  moduleServer(
    id,
    function(input, output, session) {
      output$plot<-renderPlotly({
        
        fig <- plot_ly(data=city(), x = ~as.factor(year), y = ~count, type = 'scatter', mode = 'markers+lines')
        
        fig%>% layout(title = paste("Count of", sci(),"through the years"),
                      xaxis = list(title = "Years",tickangle=45),
                      yaxis = list (title = "Count"))
      })
    })
}
# Build ui & server and then run
ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(sideUI("side")),
  dashboardBody(mapUI("mapUK"), plotUI("plotPl"))
)
server <- function(input, output, session) {
  
  # use the reactive in another module
  city_input <- sideServer("side")
  mapServer("mapUK", city_input$react)
  plotServer("plotPl", city_input$counted, sci = city_input$sci)
  
}
shinyApp(ui, server)

What I have changed and didn't describe above is that from this:我已经改变并且没有在上面描述的是:

counted<-reactive({data.frame(react() %>% 
                                      group_by(year) %>% 
                                      summarise(count=n()
                                      ))
      })

I have removed data.frame() function.我已经删除data.frame() function。 You don't need this, it will be data.frame even without this function.你不需要这个,即使没有这个 function,它也会是data.frame

I have also changed mode = 'lines' into mode = 'markers+lines' , because I saw no data in plot.我还将mode = 'lines'更改为mode = 'markers+lines' ,因为我在 plot 中没有看到任何数据。 But then I realized it's because for each animal is only one year in data.frame (and just with lines you can't see line if there is only one point on plot).但后来我意识到这是因为每只动物在data.frame中只有一年(如果只有一个点,只有lines你看不到线条)。 I understand that you posted just a part of data.我了解到您仅发布了部分数据。 That's of course fine.那当然没问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在闪亮的应用程序中的同一文件中下载两个不同的数据框 - How to download two different dataframes in the same file in a shiny app 如何将绘图可视化显示到闪亮的应用程序中 - How to display plotly visualizations into shiny app 如何使用模块化闪亮应用程序阅读,显示和下载excel - how to read, display and download excel using modularized shiny app 在模块化 shiny 应用程序中点击 actionButton() 后显示带有 plot 的框 - Display box with plot after hitting actionButton() in modularized shiny app 在基于 actionButton() 和 shinyJS() 的模块化 shiny 应用程序中显示和隐藏文本 - Show and hide text in modularized shiny app based on actionButton() and shinyJS() 你如何使两个不同的数据帧中的名称相同,以使Shiny应用程序工作? - How do you make names the same in two different dataframes for Shiny app to work? alignment 模块化 shiny 应用程序中的 ggplots - alignment of ggplots in a modularized shiny app rCharts在Shiny App中为两个图表设置了不同的大小 - rCharts different sizes for the two graphs in Shiny App 简单 Shiny 应用程序的模块化版本会产生错误 - Modularized version of a simple Shiny app produces an error 根据 shiny 仪表板中的条件显示两个动态 plotly 和 highcharter 图 - Display two dynamic plotly and highcharter plots based on condition in a shiny dashboard
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM