[英]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)
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
。return(list(element1 = _object_to_return1, element2 = _object_to_return2))
.return(list(element1 = _object_to_return1, element2 = _object_to_return2))
。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)))
。react
as previously, but city_input$react
.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
.city
,还需要counted
dataframe 的参数并input
。sci()
instead of input$sci
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.