2

A rmarkdown does not render plots made with gganinate and plotly. The app should have a select input box to choose each plot.I saw that renderImage() and renderPlotly() should be used. How will I incorporate these functions? What is the better way of writing this code. Thanks

ui <- dashboardPage(
  skin = "red",
  dashboardHeader(disable = TRUE),
  dashboardSidebar(disable = TRUE),
  dashboardBody(
    fluidRow(
      box(
        width = 8,
        title = "Chart", background = "maroon", solidHeader = TRUE,
        plotOutput("plot", height = 300)
      ),
      box(
        width = 4,
        background = "aqua", solidHeader = TRUE,
        selectInput("data", "Choose visual",
          choices = c("barchart", "histogram", "boxplot", "bars", "sbars"), selected =
            "barchart"
        )
      )
    )
  )
)

server <- function(input, output) {
  output$plot <- renderPlot({
    if (input$data == "barchart") {

      # HIV status disclosure with marital status
      myplot <- ggplot(hiv, aes(x = disclosure_status, fill = marital_status)) +
        geom_bar() +
        transition_states(marital_status)

      myplot <- myplot + enter_fade() + exit_fade()
    }


    if (input$data == "histogram") {

      # Distribution of age with marital status
      myplot <- ggplot(hiv, aes(age, fill = marital_status)) +
        geom_histogram()

      myplot <- ggplotly(myplot)
    }

    if (input$data == "boxplot") {

      # Disclosure, age and marital status
      myplot <- ggplot(hiv, aes(x = disclosure_status, y = age, fill = marital_status)) +
        geom_boxplot() +
        transition_states(marital_status) +
        shadow_wake(wake_length = 1, alpha = FALSE, wrap = FALSE)
    }

    if (input$data == "bars") {

      # Subset the column for contraception
      fp2 <- hiv %>%
        select(family_planning) %>%
        count(family_planning)

      # Pictorial count of family planning
      myplot <- ggplot(fp2, aes(family_planning, n, fill = family_planning)) +
        geom_col() +
        geom_text(aes(label = n, vjust = -0.5)) +
        theme_minimal() +
        theme(legend.position = "none", axis.title.y = element_text(angle = 0)) +
        labs(title = "Histogram of types of contraceptive")
    }

    if (input$data == "sbars") {

      # Family planning and pregnancy
      myplot <- ggplot(data = hiv, aes(x = planPreg, fill = family_planning)) +
        geom_bar(position = "dodge") +
        facet_wrap(~family_planning)

      ggplotly(myplot)
    }

    myplot
  })
}


shinyApp(ui, server)
stefan
  • 90,330
  • 6
  • 25
  • 51

1 Answers1

1

Neither gganimate nor plotly will work with renderPlot and plotOutput. plotly requires renderPlotly and plotlyOutput while for following this post you could use renderImage and imageOutput for gganimate.

To condition the type of output via a selectInput one option would be to use uiOutput and renderUI.

Using some fake data and a radioButtons instead of a selectInput:

library(shiny)
library(gganimate)
library(plotly)

ui <- fluidPage(
  radioButtons("data", "Choose", choices = c("plotly", "gganimate")),
  uiOutput("foo")
)

server <- function(input, output, session) {
  output$plotly <- renderPlotly({
    ggpenguins <- qplot(bill_length_mm, body_mass_g,
      data = palmerpenguins::penguins, color = species
    )
    ggplotly(ggpenguins)
  })

  output$gganimate <- renderImage(
    {
      anim <- ggplot(mtcars, aes(mpg, disp)) +
        geom_point(aes(color = gear)) +
        transition_states(gear, transition_length = 2, state_length = 1) +
        enter_fade() +
        exit_fade()
      anim_save("outfile.gif", animate(anim)) # New

      # Return a list containing the filename
      list(src = "outfile.gif", contentType = "image/gif")
    },
    deleteFile = TRUE
  )

  output$foo <- renderUI({
    if (input$data == "plotly") {
      plotlyOutput("plotly")
    } else {
      imageOutput("gganimate")
    }
  })
}

shinyApp(ui, server)
#> 
#> Listening on http://127.0.0.1:3089

stefan
  • 90,330
  • 6
  • 25
  • 51