Shiny apps構(gòu)建好之后矿酵,其運(yùn)行與反應(yīng)要快速才會(huì)吸引用戶全肮;因此棘捣,在構(gòu)建Shiny apps時(shí),耗時(shí)計(jì)算代碼的放置顯得尤為重要评疗。
#例子 - stockVis
##創(chuàng)建stockVis Shiny app
- 創(chuàng)文件夾:stockVis
- 下載: app.R 和helpers.R
- 安裝quantmod包:install.packages("quantmod")
- 運(yùn)行:runApp("stockVis")
stockVis應(yīng)用程序根據(jù)股票代碼查找股票價(jià)格茵烈,并將結(jié)果顯示為折線圖。
- 選擇要檢查的股票
- 選擇一系列要回顧的日期
- 選擇是否在y軸上繪制股票價(jià)格或股票價(jià)格的對數(shù)加匈,
- 決定是否根據(jù)通貨膨脹調(diào)整價(jià)格仑荐。
注:注意,“為通貨膨脹調(diào)整價(jià)格”復(fù)選框還不能工作粘招。本節(jié)的任務(wù)之一是修復(fù)這個(gè)復(fù)選框。
默認(rèn)情況下示姿,stockVis會(huì)顯示SPY代碼(整個(gè)標(biāo)普500的一個(gè)指數(shù))逊笆。要查找不同的股票,請鍵入雅虎財(cái)經(jīng)能夠識別的股票符號难裆。你可以在這里查看雅虎的股票代碼:here。一些常見的符號是GOOG(谷歌)褂痰、AAPL (Apple)和GS (Goldman Sachs)症虑。
stockVis非常依賴quantmod包中的兩個(gè)功能:
- 使用getsymbols直接從雅虎財(cái)經(jīng)(Yahoo finance)和圣路易斯聯(lián)邦儲(chǔ)備銀行(Federal Reserve Bank of St. Louis)等網(wǎng)站下載金融數(shù)據(jù)。
- 使用chartSeries在一個(gè)吸引人的圖表中顯示價(jià)格谍憔。
- stockVis還依賴于一個(gè)名為helpers.R腳本主籍。它包含一個(gè)根據(jù)通貨膨脹調(diào)整股票價(jià)格的函數(shù)千元。
#復(fù)選框和日期范圍
stockVis應(yīng)用程序使用了一些新的小部件:
- 日期范圍選擇器颤绕,使用dateRangeInput
- 用checkboxInput創(chuàng)建的幾個(gè)復(fù)選框。復(fù)選框小部件非常簡單奥务。當(dāng)復(fù)選框被選中時(shí),它們返回TRUE议纯,當(dāng)復(fù)選框未被選中時(shí)返回FALSE溢谤。
- 這些復(fù)選框在ui對象中被命名為log和adjust,這意味著您可以在服務(wù)器函數(shù)中將它們作為input
adjust進(jìn)行查找阀参。
#簡化計(jì)算
檢查當(dāng)您點(diǎn)擊“在對數(shù)尺度上繪制y軸”時(shí)會(huì)發(fā)生什么。input$log的值會(huì)改變蛛壳,這會(huì)導(dǎo)致renderPlot中的整個(gè)表達(dá)式重新運(yùn)行:
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)
})
當(dāng)renderPlot重新運(yùn)行時(shí):
- 它使用getSymbols從Yahoo finance重新獲取數(shù)據(jù)
- 它重新繪制圖表所刀。
這并不好,因?yàn)槟恍枰匦芦@取數(shù)據(jù)來重新繪制繪圖忧吟。事實(shí)上斩披,如果你過于頻繁地重新獲取數(shù)據(jù),雅虎財(cái)經(jīng)(Yahoo finance)會(huì)切斷你的服務(wù)(因?yàn)槟汩_始看起來像個(gè)爬蟲機(jī)器人)垦沉。但更重要的是,重新運(yùn)行g(shù)etSymbols是不必要的工作寡壮,這會(huì)降低應(yīng)用程序的速度并消耗服務(wù)器。
#響應(yīng)表達(dá)式
可以限制在使用反應(yīng)表達(dá)式的反應(yīng)期間重新運(yùn)行的內(nèi)容诬像。
使用reactive函數(shù)創(chuàng)建一個(gè)響應(yīng)表達(dá)式,就像渲染render*函數(shù)。
例如,下面是一個(gè)反應(yīng)式表達(dá)式邪乍,它使用stockVis的小部件從Yahoo獲取數(shù)據(jù)。
dataInput <- reactive({
getSymbols(input$symb, src = "yahoo",
from = input$dates[1],
to = input$dates[2],
auto.assign = FALSE)
})
當(dāng)您運(yùn)行表達(dá)式時(shí)榜配,它將運(yùn)行g(shù)etSymbols并返回結(jié)果。您可以通過調(diào)用dataInput()在renderPlot中使用價(jià)格數(shù)據(jù)蛋褥。
output$plot <- renderPlot({
chartSeries(dataInput(), theme = chartTheme("white"),
type = "line", log.scale = input$log, TA = NULL)
})
響應(yīng)表達(dá)式比常規(guī)R函數(shù)更聰明一些睛驳。它們緩存數(shù)據(jù)。并知道它們的值何時(shí)已經(jīng)更新淫茵。
第一次運(yùn)行反應(yīng)表達(dá)式時(shí),該表達(dá)式將其結(jié)果保存在計(jì)算機(jī)的內(nèi)存中匙瘪。下一次調(diào)用響應(yīng)表達(dá)式時(shí)蝶缀,它可以返回這個(gè)保存的結(jié)果,而不進(jìn)行任何計(jì)算(這會(huì)使應(yīng)用程序更快)翁都。
反應(yīng)表達(dá)式只有在知道結(jié)果是最新的情況下才會(huì)返回保存的結(jié)果。如果反應(yīng)表達(dá)式獲悉結(jié)果已經(jīng)更新了(因?yàn)楦淖兞诵〔考?,表達(dá)式將重新計(jì)算結(jié)果骑冗。然后返回新的結(jié)果并保存一個(gè)新的副本先煎。反應(yīng)表達(dá)式將使用這個(gè)新的副本,直到它也更新為止薯蝎。
reactive()優(yōu)勢:
- 反應(yīng)式表達(dá)式在第一次運(yùn)行時(shí)保存其結(jié)果。
- 下一次調(diào)用響應(yīng)表達(dá)式時(shí)袒哥,它檢查保存的值是否已更新(即,它所依賴的小部件是否已更改)堡称。
- 值沒更新,就可以調(diào)用先前保存的值桐臊,不進(jìn)行任何計(jì)算晓殊;更新了的話,重新運(yùn)算表達(dá)式計(jì)算結(jié)果巫俺。
可以用reactive()來防止Shiny重新運(yùn)行不必要的代碼∪次耍考慮一下反應(yīng)表達(dá)式將如何在下面的新stockVis應(yīng)用程序中工作。
server <- function(input, output) {
dataInput <- reactive({
getSymbols(input$symb, src = "yahoo",
from = input$dates[1],
to = input$dates[2],
auto.assign = FALSE)
})
output$plot <- renderPlot({
chartSeries(dataInput(), theme = chartTheme("white"),
type = "line", log.scale = input$log, TA = NULL)
})
}
當(dāng)你點(diǎn)擊“Plot y axis on the log scale”稽穆,輸入input$log將改變赶撰,renderPlot將重新執(zhí)行。
- renderPlot將調(diào)用dataInput()
- dataInput將檢查dates和symb小部件是否沒有更改
- dataInput將返回其保存的股票價(jià)格數(shù)據(jù)集餐胀,而無需重新從雅虎獲取數(shù)據(jù)
- renderPlot將用選擇的的軸表達(dá)方式重新繪制圖表。
#依賴性
當(dāng)在Shiny app修改了股票代碼否灾,Shiny 也會(huì)知道鸣奔,并且重新畫圖。
當(dāng)遇到以下兩種情況挎狸,Shiny會(huì)重新運(yùn)行:
- 對象的render*函數(shù)中的input中的值發(fā)生變化,
- 對象的render*函數(shù)中的反應(yīng)性表達(dá)式已經(jīng)更新
可以將反應(yīng)表達(dá)式看作連接崭别,鏈接input和output中的對象。output中的對象將響應(yīng)鏈中任何下游所做的更新舞痰。(可以設(shè)計(jì)一個(gè)長鏈,因?yàn)榉磻?yīng)表達(dá)式可以調(diào)用其他反應(yīng)表達(dá)式)
#修復(fù) “Adjust prices for inflation”
現(xiàn)在來修復(fù) “Adjust prices for inflation”响牛,用戶就能夠根據(jù)通貨膨脹調(diào)整的價(jià)格和未調(diào)整的價(jià)格之間切換赫段。
server <- function(input, output) {
dataInput <- reactive({
getSymbols(input$symb, src = "yahoo",
from = input$dates[1],
to = input$dates[2],
auto.assign = FALSE)
})
output$plot <- renderPlot({
data <- dataInput()
if (input$adjust) data <- adjust(dataInput())
chartSeries(data, theme = chartTheme("white"),
type = "line", log.scale = input$log, TA = NULL)
})
}
#總結(jié)
通過使用reactive()模塊化代碼,可以加快應(yīng)用程序的速度.
- reactive()接受輸入值或其他反應(yīng)表達(dá)式的值,并返回一個(gè)新值
- reactive()保存它們的結(jié)果坯台,并且只會(huì)在輸入發(fā)生更改時(shí)重新計(jì)算
- 使用reactive({ })創(chuàng)建響應(yīng)表達(dá)式
- 調(diào)用reactive()結(jié)果,使用reactive expressions名稱加括號
- dataInput <- reactive({})的結(jié)果調(diào)用方法是dataInput();dataInput() 中有多個(gè)對象時(shí)蜒蕾,使用dataInput()$對象名調(diào)用
- 只有在
reactive()
或render*
中可以使用reactive()
#原文:
系列文章:
R shiny教程-1:一個(gè) Shiny app的基本組成部分
R shiny教程-2:布局用戶界面
R shiny教程-3:添加小部件到Shiny App
R shiny教程-4:Shiny app響應(yīng)式結(jié)果展示
R shiny教程-5:調(diào)用R程序和導(dǎo)入數(shù)據(jù)
Shiny Server安裝