2
votes

I am trying to name the legends of a ggplot in Shiny. The problem is that since the user can turn off and on the lines the names for each line change the first name of a legend is associated with the first visible line.

I need a way to rename the Legends.

The data:

data_raw <- structure(list(Group.1 = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 1L, 2L, 3L, 4L, 5L, 7L, 1L, 2L, 3L, 4L, 5L, 6L, 7L), .Label = c("2016-07-01", "2016-08-01", "2016-09-01", "2016-10-01", "2016-11-01", "2016-12-01", "2017-01-01"), class = "factor"), Group.2 = c(101, 101, 101, 101, 101, 101, 101, 103, 103, 103, 103, 103, 103, 105, 105, 105, 105, 105, 105, 105), x = c("57976", "42933", "49731", "46808", "48938", "41937", "41932", "48900", "37625", "57700", "41700", "57600", "48800", "46102", "35796", "42490", "46755", "46757", "46810", "45232")), .Names = c("Group.1", "Group.2", "x"), row.names = c(NA, 20L), class = "data.frame")

the Code:

library(shiny)
library(ggplot2)

ui <- fluidPage(

    titlePanel("Legends"),

    sidebarLayout(position = "left",
                  sidebarPanel(checkboxGroupInput("checkGroup", 
                                                  label = h3("Postnumber"), 
                                                  choices = list( 
                                                          "101" = 101, 
                                                          "103" = 103, 
                                                          "105" = 105),
                                                    selected = "101"
                                                 )),
             mainPanel("main panel", 
                    plotOutput('myplot'))
    ))

server <- function(input, output) { 

    output$myplot <- renderPlot({

    grouped_data <- data_raw[data_raw$Group.2 %in% input$checkGroup,]

    p <- ggplot(grouped_data, aes(Group.1, x, group = Group.2)) +
            scale_colour_manual(values=c("#999999", "#E69F00", "#56B4E9"), 
                                labels=c("postnr 101", "postnr 103", "postnr 105"))
    p + geom_line() +
            theme(axis.title.y=element_text(margin=margin(0,20,0,0))) +
            geom_line(data = grouped_data, aes(colour = factor(Group.2)))

})
    }
shinyApp(ui = ui, server = server) # this launches your app

I if leave the legends as is (without any renaming), it uses the right name from choices list under the checkboxGroupInput, but I need the ability to rename it.

1

1 Answers

1
votes

I have modified your server function:

server <- function(input, output) { 
    output$myplot <- renderPlot({

    grouped_data <- data_raw[data_raw$Group.2 %in% input$checkGroup,]

    grouped_data$Group.2 <- paste("postnr ", grouped_data$Group.2, sep = "")

    grouped_data$Group.2 <- factor(grouped_data$Group.2,
                                   levels = c("postnr 101", "postnr 103", "postnr 105"),
                                   ordered = TRUE) 

    ggplot(grouped_data,
                aes_string(x = "Group.1", y = "x", group = "Group.2",
                           colour = "Group.2")) +
      geom_line() + 
      scale_colour_manual(values=c("#999999", "#E69F00", "#56B4E9"),
                          guide = guide_legend(title = "Postnr"), drop = FALSE) +
      theme(axis.title.y=element_text(margin=margin(0,20,0,0)))

  }) }

Label items (101, 103, 105) are renamed (to "postnr 101" etc) using:

    grouped_data$Group.2 <- paste("postnr ", grouped_data$Group.2, sep = "") 

They are then converted to an ordered factor (so that each item, e.g. "postnr 101" always gets the same colour):

    grouped_data$Group.2 <- factor(grouped_data$Group.2,
                                   levels = c("postnr 101", "postnr 103", "postnr 105"),
                                   ordered = TRUE) 

Finally, I have modified the ggplot to use aes_string (since there is a variable named x in your data.frame) and to give the legend a title using guide = guide_legend(title = "Postnr"). The drop = FALSE ensures consistent colours (since unused factor levels are not dropped).

If no checkbox is checked you will get an error, so you need to check that your grouped_data data.frame has at least 1 row before generating a plot. If nrow(grouped_data) == 0 then return NULL (no plot).