2017-10-28 86 views
1

我有一個簡單的練習:x是data.frame的一列dt。我想製作一個Shiny應用程序,打印出x的平均值。如果複選框「乘以2」被選中,則將x乘以2.如果不是那麼舊的值。避免全局更改變量

library(shiny) 
dt <- data.frame(x = 1:10, y = rep(c(2,3),5)) 

ui <- fluidPage(
    checkboxInput("myCheckbox", "multiple dt$x by 2"), 
    actionButton("myButton", "show result") 
) 

server <- function(input, output) { 
    i <- 0 

    observeEvent(input$myCheckbox,{ # if this checkbox is true then dt$x should be muiltiplied by 2 
    i <<- i + 1 
    if(i > 1){ # first call should not change dt$x 
     if(input$myCheckbox){ 
     dt$x <<- dt$x * 2 
     }else{ 
     dt$x <<- dt$x/2 
     } 
    } 
    }) 

    observeEvent(input$myButton,{ 
    showNotification(paste0("Mean of dt$x is equal ", mean(dt$x)), type="default") 
    }) 
} 

shinyApp(ui, server) 

我該如何避免那些<<-?這是有風險的,在我的更大的Shiny應用程序中有300行代碼,我有時會得到一個錯誤,說R無法選擇範圍。

+0

您是否希望多次乘以'dt $ x'?或者只是在將它乘以2並返回其原始值之間切換? –

+0

切換。正如我們在代碼中看到的那樣。 –

回答

1

可以使用reactiveValues功能反應式編程:

library(shiny) 
dt <- data.frame(x = 1:10, y = rep(c(2, 3), 5)) 

ui <- fluidPage(
    checkboxInput("myCheckbox", "multiple dt$x by 2"), 
    actionButton("myButton", "show result") 
) 

server <- function(input, output) { 
    values <- reactiveValues(x = dt$x) 
    observeEvent(input$myCheckbox, { 
    if (input$myCheckbox) { 
     values$x <- values$x * 2 
    } else { 
     values$x <- values$x/2 
    } 
    }) 
    observeEvent(input$myButton, { 
    showNotification(paste0("Mean of dt$x is equal ", mean(values$x)), type = "default") 
    print(dt$x) 
    }) 
} 

shinyApp(ui, server) 

reactiveValues函數返回一個對象,用於存儲反應性值。它可以讓你避免在全球範圍內改變變量,這正是你想要的。

1

在服務器功能中定義了一個反應版本dt。您可以使用多個輸入值來定義反應表達式。另一個選擇是設置一個reactiveValues()對象並用觀察者對其進行更新,但我認爲reactive()表達式更適合這種情況。如果您試圖定義的值完全由當前輸入值確定。如果你想用應用程序迭代操作它,那麼reactiveValues()可能會更好。

library(shiny) 
library(dplyr) 
dt <- data.frame(x = 1:10, y = rep(c(2,3),5)) 


ui <- fluidPage(
    checkboxInput("myCheckbox", "multiple dt$x by 2"), 
    checkboxInput("myOtherCheckbox", "set dt$x to 0"), 
    actionButton("myButton", "show result") 
) 


server <- function(input, output){ 
    dt2 <- reactive({ 
    mutate(dt, x = if(input$myCheckbox==TRUE){2*x} else{x}) %>% 
    mutate(x = if(input$myOtherCheckbox==TRUE){0}else{x} 
    }) 

    observeEvent(input$myButton,{ 
    showNotification(paste0("Mean of dt$x is equal ", mean(dt2()$x)), type="default") 
    }) 
} 


shinyApp(ui, server) 
+0

但是當我想用多個按鈕重新排列dt $ x多次時什麼?如果我想在相同的x上添加第二個反應:'dt2 < - reactive({input {myCheckbox2 == TRUE} {mutate(dt,x = 0)} else {dt} }' –

+0

大概把它全部放在相同的反應表達式中。您可以根據多個輸入值來定義它 –