Add legend to ggplot2 line plot

前端 未结 3 1985
长发绾君心
长发绾君心 2020-11-21 11:44

I have a question about legends in ggplot2. I managed to plot three lines in the same graph and want to add a legend with the three colors used. This is the code used

<
相关标签:
3条回答
  • 2020-11-21 12:09

    I really like the solution proposed by @Brian Diggs. However, in my case, I create the line plots in a loop rather than giving them explicitly because I do not know apriori how many plots I will have. When I tried to adapt the @Brian's code I faced some problems with handling the colors correctly. Turned out I needed to modify the aesthetic functions. In case someone has the same problem, here is the code that worked for me.

    I used the same data frame as @Brian:

    data <- structure(list(month = structure(c(1317452400, 1317538800, 1317625200, 1317711600, 
                                           1317798000, 1317884400, 1317970800, 1318057200, 
                                           1318143600, 1318230000, 1318316400, 1318402800, 
                                           1318489200, 1318575600, 1318662000, 1318748400, 
                                           1318834800, 1318921200, 1319007600, 1319094000), 
                                         class = c("POSIXct", "POSIXt"), tzone = ""),
                       TempMax = c(26.58, 27.78, 27.9, 27.44, 30.9, 30.44, 27.57, 25.71, 
                                   25.98, 26.84, 33.58, 30.7, 31.3, 27.18, 26.58, 26.18, 
                                   25.19, 24.19, 27.65, 23.92), 
                       TempMed = c(22.88, 22.87, 22.41, 21.63, 22.43, 22.29, 21.89, 20.52,
                                     19.71, 20.73, 23.51, 23.13, 22.95, 21.95, 21.91, 20.72, 
                                     20.45, 19.42, 19.97, 19.61), 
                       TempMin = c(19.34, 19.14, 18.34, 17.49, 16.75, 16.75, 16.88, 16.82, 
                                   14.82, 16.01, 16.88, 17.55, 16.75, 17.22, 19.01, 16.95, 
                                   17.55, 15.21, 14.22, 16.42)), 
                  .Names = c("month", "TempMax", "TempMed", "TempMin"), 
                  row.names = c(NA, 20L), class = "data.frame")  
    

    In my case, I generate my.cols and my.names dynamically, but I don't want to make things unnecessarily complicated so I give them explicitly here. These three lines make the ordering of the legend and assigning colors easier.

    my.cols <- heat.colors(3, alpha=1)
    my.names <- c("TempMin", "TempMed", "TempMax")
    names(my.cols) <- my.names
    

    And here is the plot:

    p <-  ggplot(data, aes(x = month))
    
    for (i in 1:3){
      p <- p + geom_line(aes_(y = as.name(names(data[i+1])), colour = 
    colnames(data[i+1])))#as.character(my.names[i])))
    }
    p + scale_colour_manual("", 
                            breaks = as.character(my.names),
                            values = my.cols)
    p
    

    0 讨论(0)
  • 2020-11-21 12:21

    Since @Etienne asked how to do this without melting the data (which in general is the preferred method, but I recognize there may be some cases where that is not possible), I present the following alternative.

    Start with a subset of the original data:

    datos <-
    structure(list(fecha = structure(c(1317452400, 1317538800, 1317625200, 
    1317711600, 1317798000, 1317884400, 1317970800, 1318057200, 1318143600, 
    1318230000, 1318316400, 1318402800, 1318489200, 1318575600, 1318662000, 
    1318748400, 1318834800, 1318921200, 1319007600, 1319094000), class = c("POSIXct", 
    "POSIXt"), tzone = ""), TempMax = c(26.58, 27.78, 27.9, 27.44, 
    30.9, 30.44, 27.57, 25.71, 25.98, 26.84, 33.58, 30.7, 31.3, 27.18, 
    26.58, 26.18, 25.19, 24.19, 27.65, 23.92), TempMedia = c(22.88, 
    22.87, 22.41, 21.63, 22.43, 22.29, 21.89, 20.52, 19.71, 20.73, 
    23.51, 23.13, 22.95, 21.95, 21.91, 20.72, 20.45, 19.42, 19.97, 
    19.61), TempMin = c(19.34, 19.14, 18.34, 17.49, 16.75, 16.75, 
    16.88, 16.82, 14.82, 16.01, 16.88, 17.55, 16.75, 17.22, 19.01, 
    16.95, 17.55, 15.21, 14.22, 16.42)), .Names = c("fecha", "TempMax", 
    "TempMedia", "TempMin"), row.names = c(NA, 20L), class = "data.frame")
    

    You can get the desired effect by (and this also cleans up the original plotting code):

    ggplot(data = datos, aes(x = fecha)) +
      geom_line(aes(y = TempMax, colour = "TempMax")) +
      geom_line(aes(y = TempMedia, colour = "TempMedia")) +
      geom_line(aes(y = TempMin, colour = "TempMin")) +
      scale_colour_manual("", 
                          breaks = c("TempMax", "TempMedia", "TempMin"),
                          values = c("red", "green", "blue")) +
      xlab(" ") +
      scale_y_continuous("Temperatura (C)", limits = c(-10,40)) + 
      labs(title="TITULO")
    

    The idea is that each line is given a color by mapping the colour aesthetic to a constant string. Choosing the string which is what you want to appear in the legend is the easiest. The fact that in this case it is the same as the name of the y variable being plotted is not significant; it could be any set of strings. It is very important that this is inside the aes call; you are creating a mapping to this "variable".

    scale_colour_manual can now map these strings to the appropriate colors. The result is enter image description here

    In some cases, the mapping between the levels and colors needs to be made explicit by naming the values in the manual scale (thanks to @DaveRGP for pointing this out):

    ggplot(data = datos, aes(x = fecha)) +
      geom_line(aes(y = TempMax, colour = "TempMax")) +
      geom_line(aes(y = TempMedia, colour = "TempMedia")) +
      geom_line(aes(y = TempMin, colour = "TempMin")) +
      scale_colour_manual("", 
                          values = c("TempMedia"="green", "TempMax"="red", 
                                     "TempMin"="blue")) +
      xlab(" ") +
      scale_y_continuous("Temperatura (C)", limits = c(-10,40)) + 
      labs(title="TITULO")
    

    (giving the same figure as before). With named values, the breaks can be used to set the order in the legend and any order can be used in the values.

    ggplot(data = datos, aes(x = fecha)) +
      geom_line(aes(y = TempMax, colour = "TempMax")) +
      geom_line(aes(y = TempMedia, colour = "TempMedia")) +
      geom_line(aes(y = TempMin, colour = "TempMin")) +
      scale_colour_manual("", 
                          breaks = c("TempMedia", "TempMax", "TempMin"),
                          values = c("TempMedia"="green", "TempMax"="red", 
                                     "TempMin"="blue")) +
      xlab(" ") +
      scale_y_continuous("Temperatura (C)", limits = c(-10,40)) + 
      labs(title="TITULO")
    

    0 讨论(0)
  • 2020-11-21 12:23

    I tend to find that if I'm specifying individual colours in multiple geom's, I'm doing it wrong. Here's how I would plot your data:

    ##Subset the necessary columns
    dd_sub = datos[,c(20, 2,3,5)]
    ##Then rearrange your data frame
    library(reshape2)
    dd = melt(dd_sub, id=c("fecha"))
    

    All that's left is a simple ggplot command:

    ggplot(dd) + geom_line(aes(x=fecha, y=value, colour=variable)) +
      scale_colour_manual(values=c("red","green","blue"))
    

    Example plot

    enter image description here

    0 讨论(0)
提交回复
热议问题