查看原文
其他

R语言 | 使用shiny的reactive表达式写应用程序

猫哥 大邓和他的Python
2024-09-09

作者: 猫哥

波恩大学经济学专业,计量经济学方向


在之前的推文中,我们介绍了如何在R语言中,用Shiny包编写应用程序App。在这篇推文中,我们将要介绍Shiny包中一类独特且重要的表达式:reactive expressions。

在设计App时,我们希望App能够有较快的响应速度。但是,如果App的server函数中包含很多耗时较长的运算,那么应该怎么办呢?此时,就需要用到Reactive表达式。它能够控制程序中哪些部分需要更新运算,而哪些部分不需要更新,从而节省运算时间。


案例:stockVis

此处,我们将通过一个案例来讲解reactive表达式。下图是stockVis的App界面,这个App能够帮助用户描绘相应股票的价格变动。感兴趣的读者可以根据此处的提示下载该App。

根据上图可以看出,用户需要首先选择股票(Symbol),然后选择观察时期(Data range),再选择绘制原股票价格还是对数化后的股票价格,最后再选择是否股价中的通胀进行矫正。

在对这些选项进行了选择之后,stockVis首先用getSymbols函数从诸如Yahoo finance和Federal Reserve Bank of St. Louis这样的网站中下载金融数据到R,然后再用chartSeries将股价描绘出来。

server函数中,用来生成图形的程序如下。在分析了该程序之后,我们会发现一个问题。比如,当我们重新选中“Plot y axis on the log scale”,那么input$log的值就会变化,那么就会导致整个renderPlot重新进行运算。

output$plot <- renderPlot({
  data <- getSymbols(input$symb, src = "yahoo",
                     from = input$dates[1],
                     to = input$dates[2],
                     auto.assign = FALSE)

  chartSeries(data, theme = chartTheme("white"),
              type = "line", log.scale = input$log, TA = NULL)
})

renderPlot每次重新运算时,首先会重新用getSymbols抓去数据,然后用chartSeries重新画图。然而,用getSymbols从Yahoo等网站抓取数据所花费的时间并不是可以忽略不计的。另外,如果抓取的过于频繁,我们的IP地址会被屏蔽,这是网站将我们错判为机器人,也是网站应对爬虫的常用做法。最关键的是,当我们只是重新选择“Plot y axis on the log scale”,我们并不希望重新抓取数据,而是希望在原有数据的基础上对数化即可。


Reactive表达式

在遇到上述问题时,我们就需要用到reactive表达式。reactive表达式以ui函数里各种input变量作为输入。如下,reactive表达式的输入则是input$symbinput$dates。当input$symbinput$dates的值变化时,此处reactive表达式的输出结果才会发生变化,而不受input$log的影响。

dataInput <- reactive({
  getSymbols(input$symb, src = "yahoo",
    from = input$dates[1],
    to = input$dates[2],
    auto.assign = FALSE)
})

所以,我们现在用上面的reactive表达式更新原先的程序,得到如下程序。dataInput()命令则是运行如上的reactive表达式。此时,如果我们只重新选择"Plot y axis on the log scale",那么reactive表达式里的数据抓取过程并不会更新,而只有renderPlot里的log.scale参数会更新,这将节省程序运行时间,而且减少数据抓取次数,防止IP地址被封。

output$plot <- renderPlot({    
  chartSeries(dataInput(), theme = chartTheme("white"),
    type = "line", log.scale = input$log, TA = NULL)
})

reactive表达式不止reactive(),还包括observe(), observeEvent()eventReactive()等等,详见此处。另外,reactive表达式只能包装在特定的、允许reactive表达式的函数中,如此处的renderPlot,而不能被包装在plot函数中。render*类函数都允许reactive表达式。


总结

Reactive表达式的功能可被简单地总结为以下步骤:

  • 当你第一次运行程序时,reactive表达式会缓存运行结果。
  • 当你下一次运行程序时,reactive表达式会自动检测输入值是否是最新的。在上例中,也就是说输入的input$symbinput$dates是否有变化。
  • 如果有变化,则reactive会根据新输入值更新结果。
  • 如果没变化,则reactive会直接使用缓存中的值。

参考文献

https://shiny.rstudio.com/tutorial/written-tutorial/lesson6/

精选文章

从符号到嵌入:计算社会科学的两种文本表示

资料 | 量化历史学与经济学研究

长期征稿 | 欢迎各位前来投稿

17G数据集 | 深交所企业社会责任报告

百度指数 | 使用qdata采集百度指数

推荐 | 社科(经管)文本分析快速指南

视频分享 | 文本分析在经管研究中的应用

MS | 使用网络算法识别创新的颠覆性与否

使用cntext训练Glove词嵌入模型

认知的测量 | 向量距离vs语义投影

Wordify | 发现和区分消费者词汇的工具

在jupyter中显示pdf内容

EmoBank | 中文维度情感词典

Asent库 | 英文文本数据情感分析

视频专栏课 | Python网络爬虫与文本分析

PNAS | 文本网络分析&文化桥梁Python代码实现

BERTopic库 | 使用预训练模型做话题建模

tomotopy | 速度最快的LDA主题模型

管理世界 | 使用文本分析词构建并测量短视主义

Wow~70G上市公司定期报告数据集

100min视频 | Python文本分析与会计

在jupyter内运行R代码

blogdown包 | 使用R语言维护Hugo静态网站
R语言 | 使用posterdown包制作学术会议海报
R语言 | 使用officedown包在Rmarkdown中制作PPT
R语言 | 使用ggsci包绘制sci风格图表

R语言 | 将多个txt汇总到一个csv文件中

继续滑动看下一个
大邓和他的Python
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存