作为Shiny平台构建与R包开发教程的第三小节,本节向读者展示如何利用Shiny server输出自己想要的数据,包括Rplot、Table、Text等信息。
数据输出机制
仍以上一节的案例为基础:
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)
上一节解释了数据输入Shiny server的机理,阐明了fileInput
–input$input_id
组合在数据输入中的作用。数据输出的机理类似,其核心是Funcoutput
–renderFunc
函数组合,其中Func可以是Table、Plot、Text甚至是Plotly等等。renderFunc
中的第一个参数定义了数据输出区域的id,这一id就被追加在server的output变量中。采用output$output_id
即可完成server与ui的对接。
随后,output$output_id
被赋上renderFunc
函数的返回值。renderFunc
中的表达式是个“reactive表达式”,即任意事件的发生都会导致该表达式的值被重新计算,以确保它的值与服务器的最新状态匹配。表达式的末尾语句相当于该表达式的返回值。该值也成为了输出的最终内容。在上述案例中,server最终显示的内容是head(dat1)
,用于打印上传数据的头部,以提醒用户的确成功地把数据传送到了服务器上。
对于其他类型的输出,只需依葫芦画瓢。
Plotly
plotly
包支持shiny接口,能实现shiny网页的动态可视化,从而显著提升用户体验感。同时,plotly
的ggplotly
函数又能很好地与强大的绘图包ggplot2
包构建良好的联系,因而实际上成为了renderPlot
方法的优良替代品。
Expmeasure
包(见教程首页)的Trend 2D模块就是一个很好的例子:
#This case will NOT run
ui.trend.2D_Plot <- fluidPage(
sidebarLayout(
sidebarPanel(fluidRow(column(12, align = "center",
actionBttn(
inputId = "trend_2DPlot_APPLY",
label = "APPLY!",
style = "pill",
color = "danger"
) )),
uiOutput("trend_2DPlot_pick1d_explantory"),
width = 3),
#**************Notice***************
mainPanel(plotlyOutput('trend_2DPlot_plot1', height = "600px"), width = 9)
#**************Notice***************
)
)
server <- function(input, output){
#...Codes omitted
trend.2Dplot <- function(dat, x, y){
txt1 <- paste("dat$",x,sep='')
txt2 <- paste("dat$",y,sep='')
g <- ggplot(dat, aes(eval(parse(text = txt1)), eval(parse(text = txt2)))) +
geom_smooth() + geom_point() +
xlab(x) + ylab(y)
#**************Notice***************
return(plotly::ggplotly(g))
#**************Notice***************
}
output$trend_2DPlot_pick1d_explantory <- renderUI({
pickerInput(
inputId = "trend_2DPlot_pick1_explantory",
label = "Select explantory variable",
choices = input$data_pick2_explantory
)
})
trend_2DPlot_APPLY_click <- 0
trend_2DPlot_plot1area <- NULL
#**************Notice***************
output$trend_2DPlot_plot1 <- renderPlotly({
if(input$trend_2DPlot_APPLY > trend_2DPlot_APPLY_click){
trend_2DPlot_APPLY_click <<- trend_2DPlot_APPLY_click + 1
trend_2DPlot_plot1area <<- trend.2Dplot(read.d1(),
input$trend_2DPlot_pick1_explantory,
input$data_pick1_response)
}
trend_2DPlot_plot1area
})
#**************Notice***************
#...Codes omitted
}
其效果如图所示:
可以看到,plotly
中动态交互绘图的工具栏已经显示在Shiny界面上。尽管上述代码复杂,我们只需关注三个地方(被Notice标签包裹):
plotlyOutput
函数:第一个函数定义数据输出区域的id。第二个参数定义输出图片的高度(可有可无,但往往你会发现它还是挺有用的)。trend.2Dplot
自定义函数末尾的ggplotly
函数,将一个ggplot
转化为plotly
的格式。output
变量后跟上数据输出区域的id,从而与ui对接。renderPlotly
函数的最后一行返回一个plotly
绘图对象,最终使目标区域绘出图像。renderPlotly
函数内部代码有些复杂,在本节无需关注,这在下节内容中会详细说明。
动态ui
您可能希望一些Shiny控件会随着用户上传的数据而动态变化。这在上述代码中也已经实现。动态输出ui事实上也是数据输出的一个特殊案例,其核心是uiOutput
–renderUI
函数组合,其机理与其他数据输出没有太大差异,只不过renderUI
函数输出是一个UI而已。
上一篇: Shiny平台构建与R包开发(二)——数据输入
下一篇: Shiny平台构建与R包开发(四)——按钮与响应事件