Categories
日常应用

Shiny的架构浅析

不是说学一门语言学的不仅仅是他的语法,更重要的是他背后的思想么?R本身是个大杂烩,ggplot可以单独拎出来作为一门语言学,shiny其实也可以单独拎出来学一番。

只是简单的实现一个shiny app确实不难,就像官网上一进去看到的那个例子那样。基本上如果只是做一些比较简单的可控的dashboard,shiny的代码无非就是写的细致一点,谈不上什么架构之类的。

直到某一天...你发现这东西还可以玩的更深,然后就毅然跳入了下一个大坑——shiny reactivity。官网的开场白很直接

It’s easy to build interactive applications with Shiny, but to get the most out of it, you’ll need to understand the reactive programming model used by Shiny.

然后就介绍三剑客:reactive sources, reactive conductors, and reactive endpoints。

最简单的情况:没有conductor,直接从source到endpoint。

继续拷贝官网图:

嗯,听起来不难...其实大部分情况下shiny app处理的都是这样的情况。基本上就是一个输入(input)和输出(output)的过程。最简单的,就是我们经常在shiny app里面需要处理的input对象,会读入各种用户操作带来的值,然后后面返回一个表格或者图或者文字什么的。回到官网的例子(继续拷贝官网图)

shinyServer(function(input, output) {
  output$distPlot <- renderPlot({
    hist(rnorm(input$obs))
  })
})

大概就是这么一个简单的架构。在这种架构下,自然可以写很多if else之类的在server.R中加入各种各样输入输出的组合,然后在ui.R中排列一下输入的各种框框和输出的各种图标文字什么的。

考虑conductors的情况

shiny用的稍稍熟悉了,就开始想更多的控制这个东西。其实conductor说白了有点中间变量的感觉,就是他本身并不会最终显示出来,但是作为一个中间过程存在着。比如官网一个计算Fibonacci 序列的例子:

fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2))

shinyServer(function(input, output) {
  currentFib         <- reactive({ fib(as.numeric(input$n)) })

  output$nthValue    <- renderText({ currentFib() })
  output$nthValueInv <- renderText({ 1 / currentFib() })
})

这里无非就是多了一个新的对象currentFib(跟input和output都无关),暂时的存储了一下计算过程中的变量,然后基于这个东西,又衍生了两个最终显示出来的返回值。新的架构图就多了一个conductor这样。

再复杂一点:考虑Reactive expressions

按照官网的说法,这个东西包括:

  • accessing a database
  • reading data from a file
  • downloading data over the network
  • performing an expensive computation

基本就是从其他的数据源而不是用户的input那里读数据的情况。常见的场景比如,按照用户给定的一些条件(由input传入),返回一个符合条件的数据子集。如果数据全集是会不断更新的(比如每次都应该重新load("xxx.rdata")这样),那么这个这句话就必须写在reactive里面。同理,如果直接利用input生成一句SQL然后连接数据库读取数据,那么也要写在reactive里面。

再复杂一点:自动还是手动更新

shiny默认的情况下,如果没有放submit按钮,那么就是随便一个操作就trigger整个reactive的流程。比如官网首页上,我们拖拖鼠标那个直方图就跟着变化。如果不想让他直接变化,那么简单的可以放一个submit按钮,然后只有submit之后才会变化。

如果希望更好的控制一个app界面上各个部分呢?就要动用更高级一点的actionButton

这东西还要配合一个isolate(),就是你要告诉shiny哪些东西跟着这个button变化,哪些不属于这个button的控制范围。比如官网的例子:

shinyServer(function(input, output) {
  output$distPlot <- renderPlot({
    # Take a dependency on input$goButton
    input$goButton

    # Use isolate() to avoid dependency on input$obs
    dist <- isolate(rnorm(input$obs))
    hist(dist)
  })
})

这里只有goButton被点击的时候,才会执行下面的抽随机数并画图。actionButton是随着每次点击而不断增加计数的,从0开始一直增加过去,所以可以在server.R里面利用这个button的返回值来进行流程控制。

篇外废话:

shiny有希望成长成一个可以替代php这样实现客户端和服务器端大部分交互请求的巨人么?从这点来看,Tableau还是限制太多了。

Categories
互联网产业观察

接触PHP

现在接触的所有东西几乎都是基于PHP架构的,比如我这个博客。
今天忙活了一晚上为了修改PHP模板。先后使用了三套系统,都感觉不太理想,最后一套勉勉强强符合要求。各个作者有自己不同的架构模式,这就给我的理解带来了很大的困难。
不知道PHP到底有什么巨大的魅力,至少现在我的周围用PHP的远远比ASP或者JSP的多。
终于知道了类似于PHPWIND架构的网站怎么修改模板,现在我改版权页已经很熟练了。。。汗颜啊,先学会的竟然是这个。
然后前几天花大力气改的一个网站主页现在看来用不上了,因为静态和动态之间的结合不好做,要是做的话就几乎是把所有页面都改一个遍,这工作量可谓巨大。先放一个简洁的在那里凑合着吧。
但愿我可爱的老师能满意。。来日方长我慢慢改……反正也没多少访问量……
现在努力的学习PHP的结构,随着修改这几个模版我大概已经有了个了解。果然是在实践中提高阿,能看懂别人写的东西就是修改的基础。
但是让我头痛的是VeryCMS中层的定位,它似乎不是定死的,而是动态拼接的,这就造成我删除某个部分会导致其它东西漂移,更奇怪的是我查看源码却没有发现有关定位的语句。也就是说,我能在浏览器上看到的正常的页面时必须动用他所有默认的东西……Dear!
接连因为网站的问题看来好多关于网页设计的书,听了N多讲座,不惜千里迢迢的从南新区跑到东校。我都怀疑自己到底是学什么的了。。。经济or计算机?
大概改完这两个网站的模版之后我就会潜心研究PHP更深入的东西了。从图书馆借来N多书,准备作为参考。感觉上书上的东西和实际操作起来还是有很大的区别的,很多东西都已经更新换代了。要是能方便的上网就好了,这样就可以随时看到最近的技术发展情况了,也可以更深入的了解程序。
对于网络编程来说我还是只可怜的菜鸟,不知道什么时候才可以羽翼丰满,相信不会用太多的时间的。一年,这一年我要潜心学习编程的东西。
在此,我立下一个誓言:
明年春天过C语言二级!
不仅仅是应付考试而已,我的目标是掌握所有二级设计的知识。不仅仅是语法和算法,也要进一步了解数据库方面的东西,尽快的过三级。不过,对于内存的精确控制我还是一点不懂,不知道什么时候才能达到这样的积淀来理解。
说多了,我都不知道自己称不称得上一个有着近7年网龄的网虫了。为了一些东西我一度远离了互联网最尖端好长时间了,但愿弥补回来。虽然以后不会从事这个职业,虽然以后不会像现在一样这么关注技术的更新,但是我希望在大学中好好的学点自己喜欢的东西。
嗯,继续研究我可爱的PHP~至于平面设计嘛,权当cookies好了。
对了,顺便好好学学我可怜的英语~因为,以后在Linux之下的时候,可能会使用一个全英文的版本呢!再说要把Blog逐渐的改成全英文的呢。