Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 反应型与观察型与观察型的优势_R_Shiny - Fatal编程技术网

R 反应型与观察型与观察型的优势

R 反应型与观察型与观察型的优势,r,shiny,R,Shiny,我已经阅读了所有关于反应式编程的资料。我有点困惑。以下所有方法都有效,但首选方法是什么?为什么?显然,下面的例子很简单,但是当我使用任何一种方法创建一个更大的应用程序时,我会遇到麻烦吗 我一直倾向于服务器代码#1中的风格。原因是,我能够分解if语句。对我来说,这似乎更具可读性。同样,下面的简单示例并不十分复杂,但您可以很容易地想象,服务器代码2和服务器代码3如何与大量嵌套的if/if-else语句混淆 用户界面代码 library(shiny) ui <- fluidPage( se

我已经阅读了所有关于反应式编程的资料。我有点困惑。以下所有方法都有效,但首选方法是什么?为什么?显然,下面的例子很简单,但是当我使用任何一种方法创建一个更大的应用程序时,我会遇到麻烦吗

我一直倾向于服务器代码#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')

)
库(闪亮)

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

这是我对这个话题的最好理解

让我们从反应式开始

被动功能允许用户监控输入或其他变化变量的状态,并返回代码中其他地方使用的值。被动变量的监视被认为是惰性的,“被动表达式使用惰性计算;也就是说,当它们的依赖项发生变化时,它们不会立即重新执行,而是等待别人调用它们。()。在示例2中可以很好地说明这一点,因为您可以在
renderText
环境中调用变量,一旦调用了被动调用中的代码,就会执行并重新计算变量

对于科学迷来说,这很像量子力学,通过调用反应变量(观察它)导致它通过重新评估而改变,太长时间

现在开始
观察

Observe与reactive类似,主要区别在于它不会将任何值返回到自身环境之外的任何其他环境,而且它也不是懒惰的。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)
reactive
创建一个变量,该变量可以通过用户输入随时间变化,仅在调用时计算“lazy”的含义

遵守
持续监控反应性事件和变量,只要环境(观察到的环境)中的任何反应性变量发生变化,就会对代码进行评估。可以更改先前定义的反应性变量的值,不能创建/返回变量

observeEvent
(多米诺骨牌效应) 持续监控一个
定义的反应变量/事件(触发器),并在触发器被该触发器的更改/输入激活时运行代码。可以更改先前定义的反应变量的值,不能创建/返回变量

eventReactive
创建一个变量,该变量具有一个类似于
observeEvent
的已定义触发器。如果需要一个因触发器而计算的反应变量,而不是在调用它时,请使用此选项


我希望这会有所帮助,如果我的理解有误,或者可能会有更多的澄清,请随意编辑此答案。

已经有一个非常详细的答案,因此我只需添加我自己的简短的两美分:

只要有可能,就坚持使用
reactive()
表达式只告诉shiny如何计算变量,而不必指定何时计算变量。shiny将负责确定何时计算变量。它们将被延迟计算(仅在需要时),他们将缓存自己的价值,他们将使用书签功能-这正是shiny的设计方式,应该始终是首选

有了
reactiveValues()
,您现在又回到了更命令式编程的领域,而不是被动的领域。有一些情况下
reactiveValues()
无法解决问题,您需要使用
reactiveValues()
(或
reactiveVal()
),但只有在
reactive()时才应该使用它们
将不起作用。例如,使用
reactive()
时,只有一个地方定义了变量,因此如果要在多个地方定义变量,则需要使用
reactiveValues()
。有关
reactive()
reactiveValues()之间差异的更完整解释
,您可以看到


observeEvent()
vs
observeEvent()
:您可以将它们视为同一件事,但
observeEvent()
只是由某些变量触发的
observeEvent()
的快捷方式,其余代码是
isolate()
-ed。事实上,您对
observeEvent()所做的一切
也可以通过
observe()
来完成,这是同一事物的两种味道。

好问题,很好的例子。如果你还没有看过,你可能想看看它和它的两个答案。
如何分离({…})
与所有这些不同?它不会对内部指定的变量做出反应,在到达时执行,但仍然算作反应性环境,对吗?隔离与所有这些有什么不同?隔离通常在另一个函数中使用,但我刚刚看到了一个不使用的示例:
隔离({…})
不会对内部指定的变量做出反应,在到达时执行,但仍算作反应性环境,对吗?
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)
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)
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)
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)