Search code examples
rshinyquarto

Use early created dataframe in Shiny server


I am trying to use a created dataframe (df2 because iris is built-in) in a chunk before the shiny server chunk as input. Unfortunately, it doesn't work as expected. Here is some reproducible code:

---
title: "Object error"
format: 
  html:
    page-layout: custom
server: shiny
---

```{r}
# Created dataframe
df <- iris
df2 <- df
```

```{r}
#| panel: sidebar
vars <- unique(df2$Species)
selectInput('specie', 'Specie: ', vars)
```

```{r}
#| panel: fill
plotOutput('plot1')
```

```{r}
#| context: server
library(dplyr)
library(ggplot2)

selectedData <- reactive({
  subset(df2, Species %in% input$specie)
  })

output$plot1 <- renderPlot({
  selectedData() %>%
    ggplot(aes(x = Sepal.Length, y = Sepal.Width)) +
    geom_point()
})
```

Output:

enter image description here

As you can see the shiny server doesn't find the early created dataframe df2. So I was wondering if it is possible to use an early created dataframe in a server shiny like above in Quarto?


Edit: create dataframe in server

When creating df2 with df in the server like this doesn't work:

```{r}
#| context: server
library(dplyr)
library(ggplot2)
df2 <- df
selectedData <- reactive({
  subset(df2, Species %in% input$specie)
  })

output$plot1 <- renderPlot({
  selectedData() %>%
    ggplot(aes(x = Sepal.Length, y = Sepal.Width)) +
    geom_point()
})
```

Solution

  • I would recommend to read along Execution Context from Quarto Docs to get an idea of how variables get created at document render time and execution time from the server.

    To say briefly,

    • While the document renders, only the chunks without context: server get executed, whereas on the other hand, the chunks with context: server do not get executed, instead they are run from the server after the document is rendered (that is, in context of server).

    • So it's important to understand that, these two types of chunks are run in two completely separate R sessions.

    • Now to share data between these two sessions, we may either use context: setup or context: data and the codes of the chunk with either of these two options will execute at both render time as well as when the server is created for each new user session.

    But the context: data option seems appropriate for the chunks that are being used to load data since it saves the R object created from this chunk at render time to a Rdata file which will be then loaded during Shiny server startup.

    So You may use #| context: data,

    ```{r}
    #| context: data
    #| include: false
    
    df <- iris
    df2 <- df
    ```
    

    Also it is recommended to specify include: false to make sure that code, warnings, and output from the chunk are not included in the rendered document.

    Full Reprex

    ---
    title: "Object error"
    format: 
      html:
        page-layout: custom
    server: shiny
    ---
    
    ```{r}
    #| context: data
    #| include: false
    
    df <- iris
    df2 <- df
    ```
    
    
    ```{r}
    #| panel: sidebar
    vars <- unique(df2$Species)
    selectInput('specie', 'Specie: ', vars)
    ```
    
    ```{r}
    #| panel: fill
    plotOutput('plot1')
    ```
    
    ```{r}
    #| context: server
    library(dplyr)
    library(ggplot2)
    
    selectedData <- reactive({
      subset(df2, Species %in% input$specie)
      })
    
    output$plot1 <- renderPlot({
      selectedData() %>%
        ggplot(aes(x = Sepal.Length, y = Sepal.Width)) +
        geom_point()
    })
    ```
    

    output

    output