模块化 Shiny R 应用程序代码
Modularizing Shiny R app code
我正在尝试分离我的 Shiny 应用程序的功能以使其可重用。
我有我的 ui。我定义的 R 文件 :
tabPanel("Unemployed", source("unemployed_select.R", local=TRUE)$value),
在我的unemployed_select.R中我定义:
fluidPage(
titlePanel("Basic DataTable"),
# Create a new Row in the UI for selectInputs
fluidRow(
column(4,
selectInput("man",
"Manufacturer:",
c("All",
unique(as.character(mpg$manufacturer))))
),
column(4,
selectInput("trans",
"Transmission:",
c("All",
unique(as.character(mpg$trans))))
),
column(4,
selectInput("cyl",
"Cylinders:",
c("All",
unique(as.character(mpg$cyl))))
)
),
# Create a new row for the table.
fluidRow(
DT::dataTableOutput("table")
)
)
我的server.R文件是:
library(shiny)
library(shinythemes)
library(dataset)
shinyServer(function(input, output) {
# Filter data based on selections
output$table <- DT::renderDataTable(DT::datatable({
data <- mpg
if (input$man != "All") {
data <- data[data$manufacturer == input$man,]
}
if (input$cyl != "All") {
data <- data[data$cyl == input$cyl,]
}
if (input$trans != "All") {
data <- data[data$trans == input$trans,]
}
data
}))
})
我使用了 R 库中一个著名示例的代码 https://shiny.rstudio.com/gallery/basic-datatable.html
只是为了确保数据没有问题。数据表仍然没有呈现,所以我想这一定是定义内部源文件的问题 unemployed_select.R.
有什么想法吗?
此致
你是对的,你需要使用 source()
来加载你的模块文件,但是对于 Shiny,你需要注意 namespaces。模块和它所在的文件必须共享一个命名空间,其中事物的名称是共享的。例如,在您的模块代码中,您有这一行:
column(4,
selectInput("man",
"Manufacturer:",
c("All",
unique(as.character(mpg$manufacturer))))
但是你想让模块共享它包含的文件的命名空间,所以你需要有一种方法让包含模块的文件知道哪些部分是id,比如"man" 哪些部分是严肃的论点,例如 "Manufacturer:"
所以在 Shiny Module 中,那一行会变成
column(4,
selectInput(ns("man"),
"Manufacturer:",
c("All",
unique(as.character(mpg$manufacturer))))
此处 ns()
函数用于将 id 包含在命名空间中,这将使您声明的 id "man" 可供应用程序的其余部分使用。
这里有一个关于在 Shiny 中命名空间和编写模块的很好的指南:
https://shiny.rstudio.com/articles/modules.html
上面的 link 指出您必须命名空间 ID,必须使您的模块适合一个函数并使用 ui.R
文件中的 callModule()
调用该函数,并且必须包装tagList
而不是 fluidPage
.
中的所有内容
祝你好运!
我正在尝试分离我的 Shiny 应用程序的功能以使其可重用。
我有我的 ui。我定义的 R 文件 :
tabPanel("Unemployed", source("unemployed_select.R", local=TRUE)$value),
在我的unemployed_select.R中我定义:
fluidPage(
titlePanel("Basic DataTable"),
# Create a new Row in the UI for selectInputs
fluidRow(
column(4,
selectInput("man",
"Manufacturer:",
c("All",
unique(as.character(mpg$manufacturer))))
),
column(4,
selectInput("trans",
"Transmission:",
c("All",
unique(as.character(mpg$trans))))
),
column(4,
selectInput("cyl",
"Cylinders:",
c("All",
unique(as.character(mpg$cyl))))
)
),
# Create a new row for the table.
fluidRow(
DT::dataTableOutput("table")
)
)
我的server.R文件是:
library(shiny)
library(shinythemes)
library(dataset)
shinyServer(function(input, output) {
# Filter data based on selections
output$table <- DT::renderDataTable(DT::datatable({
data <- mpg
if (input$man != "All") {
data <- data[data$manufacturer == input$man,]
}
if (input$cyl != "All") {
data <- data[data$cyl == input$cyl,]
}
if (input$trans != "All") {
data <- data[data$trans == input$trans,]
}
data
}))
})
我使用了 R 库中一个著名示例的代码 https://shiny.rstudio.com/gallery/basic-datatable.html
只是为了确保数据没有问题。数据表仍然没有呈现,所以我想这一定是定义内部源文件的问题 unemployed_select.R.
有什么想法吗?
此致
你是对的,你需要使用 source()
来加载你的模块文件,但是对于 Shiny,你需要注意 namespaces。模块和它所在的文件必须共享一个命名空间,其中事物的名称是共享的。例如,在您的模块代码中,您有这一行:
column(4,
selectInput("man",
"Manufacturer:",
c("All",
unique(as.character(mpg$manufacturer))))
但是你想让模块共享它包含的文件的命名空间,所以你需要有一种方法让包含模块的文件知道哪些部分是id,比如"man" 哪些部分是严肃的论点,例如 "Manufacturer:"
所以在 Shiny Module 中,那一行会变成
column(4,
selectInput(ns("man"),
"Manufacturer:",
c("All",
unique(as.character(mpg$manufacturer))))
此处 ns()
函数用于将 id 包含在命名空间中,这将使您声明的 id "man" 可供应用程序的其余部分使用。
这里有一个关于在 Shiny 中命名空间和编写模块的很好的指南:
https://shiny.rstudio.com/articles/modules.html
上面的 link 指出您必须命名空间 ID,必须使您的模块适合一个函数并使用 ui.R
文件中的 callModule()
调用该函数,并且必须包装tagList
而不是 fluidPage
.
祝你好运!