Is there a way to make both TableGrob and ggplot reactive in the sample output.

Hi Experts here. I do have some clarification. I have 2 dataframes. I have populated tablegrob from 1 data and ggplot from another data. But is there a way to make them reactive. For example, I have a filter naming (Mill-A, Mill-B and so on). So as per this selection , I need to have both table and ggplot in Performance tab. I have tried myself to make this happen but unfortunately it did not happen, So asking help in this community here. Please guide me in correcting the code here. Sample code attached

---
title: "Untitled"
runtime: shiny
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
    vertical_layout: scroll
    theme: cosmo
---

```{r setup, include=FALSE}
library(flexdashboard)
library(tidyverse)
library(ggplot2)
library(shiny)
library(RGraphics)
library(gridExtra) 
```
```{r}
Performance1 <- structure(list(Mills = c("Mill-A", "Mill-B", "Mill-C", "Mill-D", 
"Mill-E"), Performance = c(0.5, 0.4, 0.2, 0.9, 0.4)), row.names = c(NA, 
-5L), class = "data.frame")
Past_Maintainence <- structure(list(Mill = c("Mill-A", "Mill-B"), `Electrical Maintainence done` = structure(c(1569283200, 
1569369600), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    `Instrumentation Maintainence done` = structure(c(1569369600, 
    1569456000), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    `Mechanical Maintainence done` = structure(c(1569456000, 
    1569283200), class = c("POSIXct", "POSIXt"), tzone = "UTC")), row.names = c(NA, 
-2L), class = "data.frame")
```
Summary
=================

Inputs {.sidebar}
-----------------------------------------------------------------------
```{r}
    selectInput("Mill1","Equipment",choices = c("All","Mill-A","Mill-B","Mill-C","Mill-D","Mill-E"),selected = "All",multiple = TRUE)
```

Column {data-width=300}
-----------------------------------------------------------------------

### Performance {data-width=10}

```{r}
output$t31 <- renderPlot({
  if (input$Mill1 != "All"){
    pd1 <- Past_Maintainence %>% filter(Mill %in% input$Mill)
  }
  if (input$Mill1 != "All"){
  tableGrob(pd1,theme = ttheme_default(base_size = 8))
    }
  })
output$g34 <- renderPlot({
  if (input$Mill != "All") {
    pd <- Performance1 %>% filter(Mills %in% input$Mill)}
  if (input$Mill != "All") {
     ggplot(data = pd,aes(x=Mills,y=Performance, fill=Performance))+geom_bar(stat = "identity",width = 0.5)+theme(plot.margin = unit(c(1,1,1,1),"cm"))+theme(axis.title.x = element_blank())+theme(axis.title.y = element_blank())+theme(legend.position = "none")+theme(axis.text.x = element_text(angle = 0,vjust = 1,size = 5))+theme(axis.text.y = element_text(angle = 0,vjust = 1,size = 5))
  }
  })
grid_layout <- rbind(c(1, 2))

output$filter_71 <- renderUI(
  if (input$Mill1 != "All") {
  plotOutput("t31")
  plotOutput("g34")  
  })
uiOutput("filter_71")
```

Your example is not reproducible, there are no t31, g34 objects (this is not the same as shiny outputs), in your plot you are mapping input$Mill1 to the x-axis but those are not columns, those are values of the Mills column, so it is not going to work, please check on this and provide a proper reproducible example.
As a hint, you can create both the table and ggplot object inside the same renderPlot() function.

1 Like

Thanks, I have re-edited my code, I was in a hurry. Yeah I have put them under renderplot. Actually I am trying to code so that both
table and ggplot (for Mill-A)
to be displayed once "Mill-A" is filtered. I have tried a lot. But not able to figure out. Could you guide me in this

The new code doesn't make sense either, if you are going to be using tableGrob() you have to stick with grid.arrange() and you can generate all inside a single renderPlot() call, see this example

---
title: "Untitled"
runtime: shiny
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
    vertical_layout: scroll
    theme: cosmo
---

```{r setup, include=FALSE}
library(flexdashboard)
library(tidyverse)
library(shiny)
library(gridExtra) 
```

```{r}
Performance1 <- structure(list(Mills = c("Mill-A", "Mill-B", "Mill-C", "Mill-D", 
"Mill-E"), Performance = c(0.5, 0.4, 0.2, 0.9, 0.4)), row.names = c(NA, 
-5L), class = "data.frame")

Past_Maintainence <- structure(list(Mill = c("Mill-A", "Mill-B"), `Electrical Maintainence done` = structure(c(1569283200, 
1569369600), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    `Instrumentation Maintainence done` = structure(c(1569369600, 
    1569456000), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    `Mechanical Maintainence done` = structure(c(1569456000, 
    1569283200), class = c("POSIXct", "POSIXt"), tzone = "UTC")), row.names = c(NA, 
-2L), class = "data.frame")
```
Summary
=================

Inputs {.sidebar}
-----------------------------------------------------------------------
```{r}
selectInput("Mill", "Equipment",
            choices = c("All","Mill-A","Mill-B","Mill-C","Mill-D","Mill-E"),
            selected = "All",
            multiple = TRUE)
```

Column {data-width=300}
-----------------------------------------------------------------------

### Performance {data-width=10}

```{r}
output$combined_plot <- renderPlot({
  req(input$Mill)
  plot_data <- Performance1
  table_data <- Past_Maintainence
  
  if (input$Mill != "All"){
    plot_data <- Performance1 %>% filter(Mills %in% input$Mill)
    table_data <- Past_Maintainence %>% filter(Mill %in% input$Mill)
  }
  
  t31 <- tableGrob(table_data, theme = ttheme_default(base_size = 8))
  g34 <- ggplot(data = plot_data,
                aes(x = Mills, y = Performance, fill = Performance)) + 
    geom_bar(stat = "identity", width = 0.5)
  
  grid_layout <- rbind(c(1, 2))
  p <- grid.arrange(t31, g34,
                    layout_matrix = grid_layout,
                    heights= c(1,1))
  print(p)
})

plotOutput("combined_plot")
```

1 Like

Cool and very perfect in your execution. Thanks a lot. This is what I wanted. Can I ask a one question. Usually I get confused when I give inputs and Outputs. For example for Tablegrob you mentioned we should use grid.arrange. So in a similar way, is there any documentation from your end so that all types of Inputs and Outputs are there?

Sorry, I'm not sure I understand what you mean, if you are not sure about which output to use on a given situation, then maybe you need to read a little bit more about how shiny works, take a look to this book.

1 Like

Yes that helps thanks again

Hi . Hope you are doing good. Just a clarification. In this question, we are calling both tablegrob and ggplot under 1 renderplot right ? But can we combing Kable function and ggplot under 1 renderplot. Nothing I just replaced tablegrob with kable(htmloutput). I tried doing this. But not getting. Can you guide as to which output function should we use?

That is because, kable produces a different kind of output (I think is HTML in this case). I'm not aware of a method to output kable tables as grobs but maybe someone else here knows a way, I recommend you to ask about this on a new topic.

1 Like

Yes it is HTML. And thanks for your suggestion. Will make a new question