Reactive variables

กรณีศึกษา: การสร้างเว็บแอปพลิเคชันด้วย Shiny ใน R

Dean Attali

Shiny Consultant

การซ้ำซ้อนของโค้ด

data <- gapminder
data <- subset(
    data,
    lifeExp >= input$life[1] & lifeExp <= input$life[2]
)
if (input$continent != "All") {
    data <- subset(
        data,
        continent == input$continent
   )
}
  • ซ้ำกัน 3 ครั้ง
    1. renderTable()
    2. renderPlot()
    3. downloadHandler()
กรณีศึกษา: การสร้างเว็บแอปพลิเคชันด้วย Shiny ใน R

Reactive variables ช่วยลดการซ้ำซ้อนของโค้ด

  • โค้ดซ้ำซ้อน ⇒ ต้องดูแลหลายจุด
    • เมื่อต้องอัปเดตโค้ด
    • เมื่อต้องแก้บัก
  • ลืมแก้บางจุดได้ง่าย ทำให้เกิดบัก
  • ใช้ตัวแปร reactive() แทนการซ้ำซ้อนของโค้ด
กรณีศึกษา: การสร้างเว็บแอปพลิเคชันด้วย Shiny ใน R

Reactive variables

output$my_table <- renderTable({
    data <- gapminder
    data <- subset(
        data,
        lifeExp >= input$life[1] & lifeExp <= input$life[2]
    )
})
my_data <- reactive({

data <- gapminder data <- subset( data, lifeExp >= input$life[1] & lifeExp <= input$life[2] )
})
output$my_table <- renderTable({ my_data() })
กรณีศึกษา: การสร้างเว็บแอปพลิเคชันด้วย Shiny ใน R

การแคชของ Reactive variables

  • Reactive variables แคชค่าของตัวเอง
  • จดจำค่าที่คำนวณไว้
  • ไม่รันใหม่หาก dependency ไม่เปลี่ยนแปลง
กรณีศึกษา: การสร้างเว็บแอปพลิเคชันด้วย Shiny ใน R

การแคชของ Reactive variables

  output$table <- renderTable({
      fit_model(input$num)
  })

  output$plot <- renderPlot({
      ggplot(
        fit_model(input$num), ...)
  })
  • fit_model() ใช้เวลา 5 วินาที
  • เรียก fit_model() 2 ครั้ง = 10 วินาที
x <- reactive({
    fit_model(input$num)
})

output$table <- renderTable({ x() })
output$plot <- renderPlot({ ggplot(x(), ...) })
  • เรียก x() 2 ครั้ง แต่โค้ดภายใน x รันเพียงครั้งเดียว
  • เรียก fit_model() ครั้งเดียว = 5 วินาที
กรณีศึกษา: การสร้างเว็บแอปพลิเคชันด้วย Shiny ใน R

Reactive variables เป็นแบบ lazy

  • Lazy variable = ยังไม่คำนวณจนกว่าจะต้องการค่า

    x <- reactive({
        fit_model(input$num)
    })
    
    output$download <- downloadHandler(
        filename = "x.csv",
        content = function(file) {
            write.csv(x(), file)
        }
    )
    
  • x() รันเฉพาะเมื่อมีการดาวน์โหลด ไม่ใช่ทุกครั้งที่ input$num เปลี่ยน

กรณีศึกษา: การสร้างเว็บแอปพลิเคชันด้วย Shiny ใน R

มาฝึกกันเถอะ!

กรณีศึกษา: การสร้างเว็บแอปพลิเคชันด้วย Shiny ใน R

Preparing Video For Download...