作为Shiny平台构建与R包开发教程的第二小节,本节向读者介绍如何利用Shiny server处理用户输入的各种信息。这些信息既包括用户向Shiny上传的数据集,也包括用户对Shiny页面的各种控件(Widget)发出的行为信号(e.g. 用户选中下拉列表框中的一个值,该值传送到server中进行后续数据处理)。本节涉及的两个内容为数据文件上传和Shiny Widget设计。
数据上传
我们希望设计一个控件,单击“Browser…”按钮,弹出选择文件对话框,让用户选择需要上传的数据文件,上传的数据用于后续分析。实现代码如下:
library(data.table)
ui.data <- fluidPage(
fileInput("data_input1", "Experiment:", accept = ".csv"),
tableOutput('data_tbout1')
)
server <- function(input, output){
read.d1 <- reactive({
inFile1 <- input$data_input1
if (is.null(inFile1)) return(NULL)
fread(inFile1$datapath)
})
output$data_tbout1 <- renderTable({
dat1 <- read.d1()
head(dat1)
})
}
shinyApp(ui.data, server)
备注:R语言函数末尾的值就是函数的返回值,代码中省略了return
函数。
上述代码中,ui部分的核心是fileInput
函数。fileInput
创造了数据输入控件。该函数的第一个参数是控件的id,第二个参数是Shiny页面中需要显示的文字,第三个参数是接受的文件类型,案例中只接受.csv文件(但在我的电脑中并不管用)。tableOutput
函数用于输出用户上传的数据,只是为了验证数据上传成功,其原理在下一节中会详细说明。
Server部分核心表达式是read.d1
。read.d1
被{}
包裹,是一个表达式。并且该表达式在reactive
函数中,表明它是一个“reactive表达式”。在Shiny中,一个“reactive表达式”会随着用户对服务器的操作而动态变化(a reactive expression is a expression whose result will change over time)。也就是说,用户上传数据,就相当于对服务器发出了一次操作,那么server函数里面所有的“reactive表达式”就要重新计算;用户在Shiny界面中选了下拉列表框中的一个值,也算对服务器发出了操作,所有“reactive表达式”也都要重新计算;用户选了一个radio button,用户拖动了slider bar,等等这些都是如此。事实上,服务器初始化也算一次事件,因此所有“reactive表达式”也要重新计算。只不过此时用户还没有上传数据,“input$data_input1”的计算结果为NULL,因此tableOutput
区域当然也不会显示任何表格。而当用户在名为"data_input1"的控件中上传数据后,表达式read.d1
需要重新计算,其中input$data_input1
应该是上传的数据文件。随后用data.table
包的fread
函数将输入的.csv文件转化为data.frame
形式。
此后,每次想调用上传的数据时,只需要使用read.d1()
就可以读取并获得data.frame
格式的数据表。
此外,用于数据输出的函数renderTable
的第一个参数同样也是“reactive表达式”,只是没有用reactive
函数显式说明。
控件设计
数据输入控件只是一个特殊的控件。事实上,多数控件的构造函数基本上都满足同一语法:shinyWidget(id, text, …)
。其中第一个参数是该控件的id。服务器必须通过识别id值来确认用户是否对该空间发出了操作。text参数往往指定了控件上需要显示什么文字。其他参数则因控件而异。具体参数用法可以通过help
函数进行查询。
这里推荐常用的Shiny控件网站:http://shinyapps.dreamrs.fr/shinyWidgets/。您可以在该网站中选择自己喜欢的控件,并将相应代码加入到自己的Shiny APP中,而用户对某一控件的选定值就等于input$控件的id
。使用时注意引入shinyWidgets
包。例如:
library(data.table)
library(shinyWidgets)
ui <- fluidPage(
awesomeCheckboxGroup(
inputId = "Id001",
label = "Checkboxes with status",
choices = c("A", "B", "C"),
inline = TRUE,
status = "danger"
),
textOutput(
outputId = "Out001"
)
)
server <- function(input, output){
output$Out001 <- renderText({
input$Id001
})
}
shinyApp(ui, server)
上一篇: Shiny平台构建与R包开发(一)——ui布局
下一篇: Shiny平台构建与R包开发(三)——数据输出
欢迎感兴趣的同行朋友们批评指正。
联系邮箱:hrwu_ecology@163.com