I’m planning to transform a large Excel model into R Shiny. Before starting to code, I’d like to clarify a few aspects. One of these involves translating the dependency logic from Excel, and I’ll explain it using a minimal example below.
Let’s assume we have one input, Input 1
, and a simple 1 × 5 data frame
. The value for Year 1
is based on real data.
Given that this method will apply to more than 200 variables, I’m wondering about the best practices for creating reactive values that:
Year 2
) or reactive data (e.g., from Year 3
onwards).Input 1
.I hope I’m not overthinking it—any feedback or suggestions would be much appreciated.
A direct translation would be to convert each formula cell into a reactive:
library(shiny)
ui <- fluidPage(
sliderInput("input_1", "Input 1", min = 0.1, max = 2, value = 1.1),
numericInput("year_1", "Year 1", value = 1),
verbatimTextOutput("result"),
)
server <- function(input, output, session) {
year_1 <- reactive(input$year_1)
year_2 <- reactive(year_1() * input$input_1)
year_3 <- reactive(year_2() * input$input_1)
year_4 <- reactive(year_3() * input$input_1)
output$result <- renderPrint({
c(year_1(), year_2(), year_3(), year_4())
})
}
shinyApp(ui, server)
This is the most general approach but may not be particularly efficient.
If you have a recursive formula it may be better to use a single reactive vector:
library(shiny)
ui <- fluidPage(
sliderInput("input_1", "Input 1", min = 0.1, max = 2, value = 1.1),
numericInput("year_1", "Year 1", value = 1),
verbatimTextOutput("result"),
)
server <- function(input, output, session) {
years <- reactive({
values <- numeric(4)
values[1] <- input$year_1
for (i in seq_along(values)[-1]) {
values[i] <- values[i - 1] * input$input_1
}
values
})
output$result <- renderPrint(years())
}
shinyApp(ui, server)
But a more idiomatic approach in R would be to find an explicit formula, if available:
library(shiny)
ui <- fluidPage(
sliderInput("input_1", "Input 1", min = 0.1, max = 2, value = 1.1),
numericInput("year_1", "Year 1", value = 1),
verbatimTextOutput("result"),
)
server <- function(input, output, session) {
years <- reactive({
input$year_1 * input$input_1^(seq_len(4) - 1)
})
output$result <- renderPrint(years())
}
shinyApp(ui, server)
There's tradeoffs to each approach, depending on the details of your application.