Using IF function in Shiny to plot different graph types

Hello Everyone,

I am creating a shiny app to display athlete data. This shiny app has multiple client-selected inputs to show data for "overview" and "Player".

I have created an IF statement that says "IF overview is selected - plot the following circular bar graph", and "IF 'Player' is selected - plot the following bar graph. Each of these graphs is created from different data and each graph works on an individual level. However, having two different graph types in this IF statement seems to create an issue where on graph will be plotted and the other will not. If I reorder (first vs second) the IF statements, the opposite graph will be plotted and the alternative graph will not be.

I hope this makes sense. If there is any issues with clarity I would love to rectify this situation. Thank you very much for your time and willingness to help. I have provided an example code below:

'''

output$plot2 <- renderPlot({
  
  if (input$Category == "Overview") {
    

    #create data frame for each player avg TOI during current season

    #add team filter, date filter

    #season filter (filters data from OCTOBER 1 of each year onwards)
    GameSheetData$Date <- as.Date(GameSheetData$Date)

    CurrYear <- year(Sys.Date())
    CurrMonth <- month(Sys.Date())
    if(CurrMonth < 10) CurrYear <- CurrYear - 1

    #filters by season, groups by player and position for avg TOI
    position_TOIavg_df <- GameSheetData %>%
                          filter(Date >= make_date(year = CurrYear, month = CurrMonth, day = 1)) %>%
                          group_by(`Player Name`, Position) %>%
                          summarise(avg_TOI = as.numeric(mean(`Time on Ice (mins)`))) %>%
                          arrange(Position, desc(avg_TOI)) %>%
                          ungroup()

    # Set a number of 'empty bar' to add at the end of each group
    empty_bar <- 2
    to_add <- data.frame( matrix(NA, empty_bar*nlevels(position_TOIavg_df$Position), ncol(position_TOIavg_df)) )
    colnames(to_add) <- colnames(position_TOIavg_df)
    to_add$Position <- rep(levels(position_TOIavg_df$Position), each=empty_bar)
    position_TOIavg_df <- rbind(position_TOIavg_df, to_add)
    position_TOIavg_df <- position_TOIavg_df %>% arrange(Position)
    position_TOIavg_df$id <- seq(1, nrow(position_TOIavg_df))

    # Get the name and the y position of each label
    label_data <- position_TOIavg_df
    number_of_bar <- nrow(label_data)
    angle <- 90 - 360 * (label_data$id-0.5) /number_of_bar     # I substract 0.5 because the letter must have the angle of the center of the bars. Not extreme right(1) or extreme left (0)
    label_data$hjust <- ifelse( angle < -90, 1, 0)
    label_data$angle <- ifelse(angle < -90, angle+180, angle)

    # Get the name and the y position of each label
    label_data <- position_TOIavg_df
    number_of_bar <- nrow(label_data)
    angle <- 90 - 360 * (label_data$id-0.5) /number_of_bar     # I substract 0.5 because the letter must have the angle of the center of the bars. Not extreme right(1) or extreme left (0)
    label_data$hjust <- ifelse( angle < -90, 1, 0)
    label_data$angle <- ifelse(angle < -90, angle+180, angle)
    
    
    # prepare a data frame for base lines
    base_data <- position_TOIavg_df %>%
                 group_by(Position) %>%
                 summarize(start=min(id), end=max(id) - empty_bar) %>%
                 rowwise() %>%
                 mutate(title=mean(c(start, end)))
    
    # prepare a data frame for grid (scales)
    grid_data <- base_data
    grid_data$end <- grid_data$end[ c( nrow(grid_data), 1:nrow(grid_data)-1)] + 1
    grid_data$start <- grid_data$start - 1
    grid_data <- grid_data[-1,]
    
    
    # Make the plot
ggplot(position_TOIavg_df, aes(x=as.factor(id), y=avg_TOI, fill=Position)) +       # Note that id is a factor. If x is numeric, there is some space between the first bar
      geom_bar(stat="identity", alpha=0.5) +
      
      # Add a val=100/75/50/25 lines. I do it at the beginning to make sur barplots are OVER it.
      geom_segment(data=grid_data, aes(x = end, y = 20, xend = start, yend = 20), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
      geom_segment(data=grid_data, aes(x = end, y = 15, xend = start, yend = 15), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
      geom_segment(data=grid_data, aes(x = end, y = 10, xend = start, yend = 10), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
      geom_segment(data=grid_data, aes(x = end, y = 5, xend = start, yend = 5), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
      
      # Add text showing the value of each 100/75/50/25 lines
      annotate("text", x = rep(max(position_TOIavg_df$id),4), y = c(5, 10, 15, 20), label = c("5", "10", "15", "20") , color="grey", size=3 , angle=0, fontface="bold", hjust=1) +
      # geom_bar(aes(x=as.factor(id), y=avg_TOI, fill=Position), stat="identity", alpha=0.5) +
      ylim(-8, 32) +
      theme_minimal() +
      theme(
        legend.position = "none",
        axis.text = element_blank(),
        axis.title = element_blank(),
        panel.grid = element_blank(),
        plot.margin = unit(rep(-1,4), "cm") 
      ) +
      coord_polar() + 
      geom_text(data=label_data, aes(x=id, y=avg_TOI+2, label=`Player Name`, hjust=hjust), color="black", fontface="bold",alpha=0.6, size=2.5, angle= label_data$angle, inherit.aes = FALSE )+
      
      # Add base line information
      geom_segment(data=base_data, aes(x = start, y = -1, xend = end, yend = -1), colour = "black", alpha=0.8, size=0.6 , inherit.aes = FALSE )  +
      geom_text(data=base_data, aes(x = title, y = -3, label=Position), hjust=c(1,1,0,0), colour = "black", alpha=0.8, size=4, fontface="bold", inherit.aes = FALSE)

     }

  if (input$Category == "Player") {
 
    df_filtered1 <- df_filtered %>% filter(Playername %in% input$Playernameinput)
    
    #ggplotly(
    ggplot(df_filtered1, aes(x=Date)) +
      geom_col (aes(y=`Practice_Duration(Avg_min)`), fill ="Black")+
      geom_point(aes(y=`Time on Ice (mins)`), 
                 size= 0.5) +
      geom_line(data=df_filtered1[!is.na(df_filtered1$`Time on Ice (mins)`),],aes(x=Date, y=`Time on Ice (mins)`), 
                colour = "Red")+
      theme_bw()+
      theme(axis.line = element_line(colour = "Black"),
            axis.text = element_text(size=8),
            axis.title = element_text(face="bold"),
            axis.text.x = element_text(angle = 45, hjust=1)) +
      scale_x_date(date_labels = "%b/%d/%y") +
      ylim (0, 100) +
      ylab("Time on Ice (mins)")
    # )
  }

'''

I have simplified this code to an extent. As I mentioned above, each graph works on an individual level, however, they do not both work based on the IF input in R shiny. In the current configuration, the IF-Player graphs works and the other does not.

Thank you for your insight and help

I am not sure if I fully understand your issue and I am not able to run your code as I don't have your data but maybe the below would work. Key is that you save your graph object as a variable and return the object outside of your if statement.

If it doesn't work try to make a minimal reproducible example using for instance the mtcars dataset. In that way people can run your code which makes it much easier to check your problem.

output$plot2 <- renderPlot({
  
  if (input$Category == "Overview") {
    
    ....
   
    # Make the plot
    p <- ggplot(position_TOIavg_df, aes(x=as.factor(id), y=avg_TOI, fill=Position))
    
    ...
    
  }
  
  if (input$Category == "Player") {
    
    ...
    
    p <- ggplot(df_filtered1, aes(x=Date))
    
    ...
  }
  
  p
  
})
2 Likes

Thank you very much for taking to the time you help. You are correct in determining what my issue was. By creating the plots as object - p then putting the object outside of the IF statements, this solves the issue and both plots are displayed as intended.

Thank you!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.