gpt4 book ai didi

r - 响应式(Reactive) vs.observe vs.observeEvent 的优势

转载 作者:行者123 更新时间:2023-12-03 09:23:00 25 4
gpt4 key购买 nike

我已经阅读了有关 Shiny 响应式(Reactive)编程的所有内容。我有点困惑。以下所有工作,但什么是首选方法,为什么?显然,下面的示例很简单,但是在使用任何方法创建更大的应用程序时会遇到麻烦吗?

我一直倾向于使用服务器代码#1 中的风格。原因是,我能够分解 if 语句。对我来说,这似乎更具可读性。同样,下面的简单示例并不是非常复杂,但您可以轻松想象服务器代码 2 和服务器代码 3 会如何因大量嵌套的 if/if else 语句而变得非常困惑。

用户界面代码

library(shiny)

ui <- fluidPage(
selectInput(inputId = 'choice',
label = 'Choice',
choice = c('Hello','Goodbye'),
selected = c('Hello')
),

textOutput('result')

)

服务器代码 1
server <- function(input,output,session)({

text <- reactiveValues()

observe({
if (input$choice == 'Hello') {
text$result <- 'Hi there'
}
})

observe({
if (input$choice == 'Goodbye') {
text$result <- 'See you later'
}
})

output$result <- renderText({
text$result
})

})

shinyApp(ui = ui, server = server)

服务器代码 2
server <- function(input,output,session)({

getStatus <- reactive({

if (input$choice == 'Hello') {
'Hi there'
} else if (input$choice == 'Goodbye'){
'See you later'
}
})

output$result <- renderText({
getStatus()
})

})

shinyApp(ui = ui, server = server)

服务器代码 3
server <- function(input,output,session)({

text <- reactiveValues()

observeEvent(input$choice,{
if (input$choice == 'Hello') {
text$result <- 'Hi there'
} else if (input$choice == 'Goodbye') {
text$result <- 'See you later'
}
})

output$result <- renderText({
text$result
})

})

shinyApp(ui = ui, server = server)

最佳答案

首先,这些东西有点模棱两可,在某些方面不是很直观,它甚至在 Shiny 博客上也这么说!

这是我对该主题的最佳理解。

让我们从 reactive 开始

响应式(Reactive)函数允许用户监视输入或其他变化变量的状态,并返回要在代码其他地方使用的值。响应式变量的监控被认为是惰性的,“响应式表达式使用惰性求值;也就是说,当它们的依赖项发生变化时,它们不会立即重新执行,而是等到它们被其他人调用。( Source) ” . 您在示例 2 中很好地展示了这一点,因为您可以在 renderText 环境中调用变量,一旦调用了响应式调用中的代码,就会执行并重新评估变量。

对于科学迷来说,这很像量子力学,通过调用 react 变量(观察它)导致它通过重新评估而改变,太多了?

现在到 observe

Observe 与reactive 类似,主要区别在于它不会向除自身之外的任何其他环境返回任何值,并且它不是惰性的。观察函数 持续监控其环境中所有反应值的任何变化 并在更改这些值时在其环境中运行代码。因此,observe 不是“懒惰”的评估,因为它在重新评估之前不会等待被调用。再次注意,您不能从观察中分配变量。

为了实验:

server <- function(input,output,session)({

observe({
if (input$choice == 'Hello') {
getStatus <- 'Hi there'
}
})

observe({
if (input$choice == 'Goodbye') {
getStatus <- 'See you later'
}
})

output$result <- renderText({
getStatus
})

})

shinyApp(ui = ui, server = server)

enter image description here

需要注意的是,在 observe中执行的代码期间,我们可以操纵外部环境 react 变量。在您的情况下,您分配 text <- reactiveValues()然后通过调用 text$result <- 'Hi there' 来操作它.我们也可以做更新 selectInput 之类的事情选择,或其他 Shiny 的小部件,但我们不能在这个环境中分配任何非 react 变量,就像上面例子中的 getStatus 一样。而这个想法是在 observe上提到的文件,

“观察者就像一个响应式(Reactive)表达式,因为它可以读取响应式(Reactive)值并调用响应式(Reactive)表达式,并且会在这些依赖项发生变化时自动重新执行。但与响应式(Reactive)表达式不同的是,它不会产生结果并且不能用作其他响应式(Reactive)表达式的输入。因此,观察者仅对它们的副作用有用(例如,执行 I/O)( Source )"

最后,observeEvent

最佳使用方法 observeEvent是将其视为已定义的触发器,因为它监视一个事件或变量的变化,然后在事件发生时触发。我最常使用它来观察按钮的输入,因为这是一个定义的事件,我希望在按下按钮后发生事情。它使用 isolate我认为这是该功能如何工作的完美名称。

在这个环境中,我们可以调用一堆 react 变量,但我们只定义一个作为触发器。 observeEvent的主要区别和 observe作为触发器,如 observe随时运行任何变化,和 observeEvent等待触发。请注意,此环境与observe 类似,因为它不返回非 react 变量。

摘要

这是一个将所有这些想法结合在一起的示例:
library(shiny)

ui<-
fluidPage(
fluidRow(
column(4,
h2("Reactive Test"),
textInput("Test_R","Test_R"),
textInput("Test_R2","Test_R2"),
textInput("Test_R3","Test_R3"),
tableOutput("React_Out")
),
column(4,
h2("Observe Test"),
textInput("Test","Test"),
textInput("Test2","Test2"),
textInput("Test3","Test3"),
tableOutput("Observe_Out")
),
column(4,
h2("Observe Event Test"),
textInput("Test_OE","Test_OE"),
textInput("Test_OE2","Test_OE2"),
textInput("Test_OE3","Test_OE3"),
tableOutput("Observe_Out_E"),
actionButton("Go","Test")
)

),
fluidRow(
column(8,
h4("Note that observe and reactive work very much the same on the surface,
it is when we get into the server where we see the differences, and how those
can be exploited for diffrent uses.")
))

)

server<-function(input,output,session){

# Create a reactive Evironment. Note that we can call the varaible outside same place
# where it was created by calling Reactive_Var(). When the varaible is called by
# renderTable is when it is evaluated. No real diffrence on the surface, all in the server.

Reactive_Var<-reactive({c(input$Test_R, input$Test_R2, input$Test_R3)})

output$React_Out<-renderTable({
Reactive_Var()
})

# Create an observe Evironment. Note that we cannot access the created "df" outside
# of the env. A, B,and C will update with any input into any of the three Text Feilds.
observe({
A<-input$Test
B<-input$Test2
C<-input$Test3
df<-c(A,B,C)
output$Observe_Out<-renderTable({df})
})

#We can change any input as much as we want, but the code wont run until the trigger
# input$Go is pressed.
observeEvent(input$Go, {
A<-input$Test_OE
B<-input$Test_OE2
C<-input$Test_OE3
df<-c(A,B,C)
output$Observe_Out_E<-renderTable({df})
})

}
shinyApp(ui, server)
reactive 创建变量 可以通过用户输入随时间更改,仅在调用时评估“懒惰”的含义。
observe持续监控 react 性事件和变量,无论何时 任何 react 变量在环境(观察到的环境)中发生变化,代码被评估。可以更改先前定义的 react 变量的值,不能创建/返回变量。
observeEvent (多米诺骨牌效应)
持续监控 定义 react 变量/事件(触发器),并在触发器被更改/输入触发时运行代码。可以更改先前定义的 react 变量的值,不能创建/返回变量。
eventReactive 创建变量 ,具有类似于 observeEvent 的定义触发器.当您想要一个因触发器而不是在调用时进行评估的 react 变量时,请使用此选项。

我希望这会有所帮助,如果我的理解有误或有更多说明,请随时编辑此答案。

关于r - 响应式(Reactive) vs.observe vs.observeEvent 的优势,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53016404/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com