【R语言】一个Shiny应用模块化的实例
发布网友
发布时间:2024-10-07 10:39
我来回答
共1个回答
热心网友
时间:2024-10-22 05:15
Shiny简介
Shiny是由Posit公司开发的双语言扩展包(包括R和Python),可视为基于R/Python的交互式应用程序开发平台,能够构建各式各样的Web应用程序。在官网上可以浏览众多实例。Shiny最出色的特点是它将众多的基础工具集成到一个高级语言环境,使用户同时具备构建前后端程序的能力。
起初的Shiny已能够支持大型Web程序的开发(实际上官网也是用Shiny构建的),但开发者注意到Shiny有必要在基础的UI和Server架构下新增模块化功能,否则随着程序功能的增加,代码管理也将愈发困难。为此,模块(Mole)在2016年首次被引入Shiny,用于将大量重复代码包装成模块,以便于移植和开发。
提示:继续阅读本文内容需要理解Shiny的最基础架构,如需了解,请移步官网教程。
Shiny模块简介
通过Shiny模块,我们可以将Shiny程序进行模块化,以下是一个示意图:
为了方便描述,以下将未模块化的Shiny应用程序称为集中式App。在这个简单的示意图中,我们虚拟一个集中式App,其中包含三个页面(Tab 1、Tab 2、Tab 3),每一个页面包含了相同的一段UI代码,且对应了一段相同的Server代码。因此,为了同时更改这三个页面的代码,我们可以将重复的UI封装成一个UI模块,再让三个页面调用模块,以此实现重复代码的缩减(server同理),构建一个模块化App。简而言之,Shiny模块本质上是一种自定义函数。
需要注意的是,server端的模块化是2020年后新增的功能,如果你之前了解的Shiny模块没有关于server端的部分,建议先去阅读最新的教学材料。
Shiny模块化实例一个集中式App
这里我们根据官网示例Shiny theme selector来构建前面示意图中集中式App的实例,代码如下:
ui.R
server.R
global.R
App的主目录结构如下:
运行程序之后我们可以发现只有Navbar 1中的Tab 1是有内容的,而Tab 2和3是空的:
Tab1的功能很简单,就是将Slider input的数字乘以10倍,再把计算公式和结果打印出来。
一个新增功能需求
现在我们自行给出一个需求,那就是将Tab 1的功能复制到Tab 2里头,并且两者相互独立。
在集中式App中新增功能
按照需求描述,最简单的方式是把Tab 1和左侧的Slider input都复制一遍,并且定义为不同的对象,如下:
ui.R
server.R
此外,global.R和App的主目录结构维持不变。
运行之后,可以发现功能已经植入Tab 2,并且能正常使用:
在模块化App中新增功能
首先我们进行UI的模块化,将sliderInput包装成一个函数slider_mole(),并单独存成一个脚本slider_mole.R
slider_mole是一个自定义函数,开头必须要定义一个函数类对象ns,内容为NS(id),其后的所有input id字符串都要套上这个函数。例如"slider"需要变更为ns("slider")。
之后,我们进行Server的模块化,将renderText包装成一个函数print_number_mole(),并单独存成一个脚本print_number_mole.R
之后,将模块插入UI端和Server端:
ui.R
server.R
global.R
App的主目录结构如下:
观察ui.R和server.R可以发现,模块是通过id进行关联的,例如txtout是由print_number_mole("slider1")生成,而其输入为slider_mole("slider1")。
模块化的优点
这里我们先总结一下集中式App和模块化App的差异。
ui端的差异主要是各项input控件是否采用自定义的模块:
server端的差异主要是各项输出是否采用自定义的模块:
如果是模块化的App,global需要source模块函数,集中式app则不需要:
通过上述对比,我们可以发现模块化的优点是它解除了计算程序和IO的1v1绑定逻辑,意味着后续对程序的更改只要在模块内进行即可,不需要满世界找代码位置,也不需要重复修改相同的代码。举个例子,现在需要将实例中sliderInput给出的数字乘以10改为乘以100,则只要在模块中修改即可。相对的,如果不采用模块化的编程方式,我们需要定位slider1和slider2所在的位置,再对代码进行修改。
结语
本文是一个关于Shiny模块的简单介绍,对于Shiny用户而言,学习Shiny模块还是很有必要的,主要原因在于集中式App框架的内容承载量非常有限,在实践中,包含数个功能的App代码已经能让人感受到生理不适(亲身经验)。此外,Shiny模块还是构建企业级Shiny应用框架的基础(例如 golem和 rhino),如果你有意在工作中使用Shiny,Shiny模块将是绕不开的一项技术。