Shiny reactive的用法與案例展示
在Shiny中跺涤,reactive()
是一個(gè)函數(shù)贩挣,用于創(chuàng)建一個(gè)響應(yīng)式變量(reactive variable)吭历。當(dāng)Shiny應(yīng)用程序的輸入?yún)?shù)或狀態(tài)改變時(shí)漏隐,這個(gè)響應(yīng)式變量會被重新計(jì)算计维,并返回一個(gè)計(jì)算結(jié)果疫鹊。換句話說曾沈,reactive()
用于定義響應(yīng)式表達(dá)式忠寻,當(dāng)輸入?yún)?shù)或狀態(tài)改變時(shí),它會自動重新計(jì)算Shiny百揭。
當(dāng)然最常用的是
reactive()
還有其他兩種類型的reactive函數(shù):
- 由 reactiveVal() 創(chuàng)建的單個(gè)響應(yīng)式值爽哎。
- 由 reactiveValues() 創(chuàng)建的響應(yīng)式值列表。
下面都會舉例演示器一。
1. 什么時(shí)候會用到 reactive
以下是一個(gè)簡單的 Shiny 應(yīng)用程序课锌,演示了如何使用 reactive() 函數(shù)。該應(yīng)用程序根據(jù)用戶輸入的兩個(gè)數(shù)字祈秕,計(jì)算它們的和并顯示結(jié)果渺贤。
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
numericInput("num1", "Enter first number:", 0),
numericInput("num2", "Enter second number:", 0),
actionButton("calculate", "Calculate")
),
mainPanel(
verbatimTextOutput("result")
)
)
)
server <- function(input, output) {
# 創(chuàng)建響應(yīng)式變量 sum
sum <- reactive({
input$num1 + input$num2
})
# 當(dāng)用戶點(diǎn)擊 Calculate 按鈕時(shí),輸出計(jì)算結(jié)果
observeEvent(input$calculate, {
output$result <- renderText(paste("The sum of", input$num1, "and", input$num2, "is", sum()))
})
}
# 運(yùn)行 Shiny 應(yīng)用程序
shinyApp(ui, server)
什么時(shí)候用到reactiveVal()
函數(shù)呢请毛?
reactiveVal()
函數(shù)與 reactive()
函數(shù)類似志鞍,都是用于創(chuàng)建響應(yīng)式變量。但是方仿,reactiveVal()
的作用對象是值而不是表達(dá)式Shiny bookdown固棚。
當(dāng)需要在 Shiny 應(yīng)用程序中創(chuàng)建一個(gè)簡單的響應(yīng)式變量時(shí),可以使用 reactiveVal()
函數(shù)仙蚜。它創(chuàng)建的變量不需要依賴其他變量或表達(dá)式此洲,而是直接返回一個(gè)初始值。與 reactive()
不同委粉,reactiveVal()
可以在任何時(shí)間更新響應(yīng)式變量的值呜师。
在這個(gè)例子中,reactiveVal() 函數(shù)用于創(chuàng)建響應(yīng)式變量 items艳丛,它的初始值是一個(gè)空向量 c()。當(dāng)用戶點(diǎn)擊添加按鈕時(shí)趟紊,observeEvent() 函數(shù)會檢測到該事件氮双,并將新項(xiàng)目添加到項(xiàng)目列表中。最后霎匈,renderUI() 函數(shù)會根據(jù)項(xiàng)目列表戴差,生成一個(gè)項(xiàng)目列表的 UI 輸出。由于響應(yīng)式變量的值可以在任何時(shí)候更新铛嘱,因此使用 reactiveVal() 函數(shù)更為方便暖释。
library(shiny)
ui <- fluidPage(
textInput("new_item", "New item:", ""),
actionButton("add_item", "Add item"),
hr(),
h4("Current items:"),
textOutput("item_list")
)
server <- function(input, output) {
# 創(chuàng)建響應(yīng)式變量 items
items <- reactiveVal(c())
# 當(dāng)用戶點(diǎn)擊添加按鈕時(shí),將新項(xiàng)目添加到列表中
observeEvent(input$add_item, {
new_item <- input$new_item
if (new_item != "") {
items(c(items(), new_item))
}
})
# 根據(jù)項(xiàng)目列表墨吓,生成項(xiàng)目列表的文本輸出
output$item_list <- renderText({
item_list <- paste(items(), collapse = "\n")
item_list
})
}
# 運(yùn)行 Shiny 應(yīng)用程序
shinyApp(ui, server)
3.什么時(shí)候用到reactiveValues()函數(shù)呢球匕?
reactiveValues()
函數(shù)可以用于創(chuàng)建包含多個(gè)響應(yīng)式變量的對象,因此可以在 Shiny 應(yīng)用程序中方便地管理多個(gè)響應(yīng)式變量帖烘。當(dāng)你需要在應(yīng)用程序中共享多個(gè)響應(yīng)式變量時(shí)亮曹,可以使用 reactiveValues()
函數(shù)。
例如reactiveValues(),在以下 Shiny 應(yīng)用程序中照卦,我們創(chuàng)建了一個(gè) reactiveValues()
對象 data式矫,其中根據(jù)數(shù)據(jù)的cut列,更改comment里面的數(shù)據(jù)役耕。
library("shiny")
library(DT)
data <- as.data.frame(ggplot2::diamonds)
data$comment <- NA
ui <- fluidPage(
selectInput(inputId = "cut",
label = "Select Cut",
choices = unique(ggplot2::diamonds$cut),
selected = "Ideal"),
actionButton(inputId = "price",
label = "Write new price"),
DTOutput("tabOut")
)
server <- function(input,session, output) {
toChange <- reactiveValues(df = data)
observeEvent(input$price, {
toChange$df[toChange$df$cut == input$cut, "price"] <- toChange$df[toChange$df$cut == input$cut, "price"] * 3
toChange$df[toChange$df$cut == input$cut, "comment"] <- paste0("updated: ", Sys.time())
output$tabOut <- renderDT({
toChange$df
})
})
observeEvent(req(input$price == 0), {
output$tabOut <- renderDT({
data
})
})
}
shinyApp(ui = ui, server = server)
當(dāng)然大家可能會遇到錯(cuò)誤Error :
這里具體問題采转,具體對待,后續(xù)會更新瞬痘,如何解決這些問題故慈。
istening on http://127.0.0.1:3371
Warning: Error in : Can't access reactive value 'divider' outside of reactive consumer.
? Do you need to wrap inside reactive() or observer()?
53: <Anonymous>
Error : Can't access reactive value 'divider' outside of reactive consumer.
? Do you need to wrap inside reactive() or observer()?
4.總結(jié)
大家可以自己邊調(diào)試邊理解。主要是用reactive()
函數(shù)图云,然后在server里面創(chuàng)建一個(gè)數(shù)據(jù)惯悠,后面就不用重復(fù)計(jì)算了。
[圖片上傳失敗...(image-de808f-1677589721185)]