admin管理员组

文章数量:1122832

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.

  1. The values for the subsequent years depend on previous years. This relationship is demonstrated in the formula view in Excel below:

  1. Additionally, Input 1 also influences these years:

Given that this method will apply to more than 200 variables, I’m wondering about the best practices for creating reactive values that:

  1. Depend on prior data (e.g., Year 2) or reactive data (e.g., from Year 3 onwards).
  2. Are also affected by Input 1.

I hope I’m not overthinking it—any feedback or suggestions would be much appreciated.

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.

  1. The values for the subsequent years depend on previous years. This relationship is demonstrated in the formula view in Excel below:

  1. Additionally, Input 1 also influences these years:

Given that this method will apply to more than 200 variables, I’m wondering about the best practices for creating reactive values that:

  1. Depend on prior data (e.g., Year 2) or reactive data (e.g., from Year 3 onwards).
  2. Are also affected by Input 1.

I hope I’m not overthinking it—any feedback or suggestions would be much appreciated.

Share Improve this question asked Nov 21, 2024 at 10:20 Grasshopper_NZGrasshopper_NZ 7555 silver badges14 bronze badges 3
  • 1 The natural way to express your sample spreadsheet in R would be with two variables: one for Input1, one for all of row 5. The row 5 variable depends on Input1. So it's not really as complicated when you put it in R. – user2554330 Commented Nov 21, 2024 at 10:46
  • Do you actually need this to be reactive? And do you need to mirror the structure of the spreadsheet? Otherwise a straightforward translation of your model would be Reduce(`*`, c(year1, rep(input1, 4L))). If you need the intermediate values, add the argument accumulate = TRUE. And of course there’s a closed formula for compound interest: year1 * input1 ^ 4. – Konrad Rudolph Commented Nov 26, 2024 at 15:38
  • Hi Konrad, thank you for your comment. Unfortunately yes, In the original Excel model all cells contain at least 2 (often 5 and more) dependences on cells from other positions/sheets. That's why I am exploring the best approach that can be used in R, rather than repeating the Excel logic. – Grasshopper_NZ Commented Nov 26, 2024 at 21:14
Add a comment  | 

1 Answer 1

Reset to default 1

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.

本文标签: Create a chain of reactive values in R ShinyStack Overflow