Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to combine and modify ggplot2 legends with ribbons and lines?

Tags:

plot

r

ggplot2

I have several issues with the legend on the following plot: enter image description here

  • Ribbons and lines are separated into 2 different legends, but I want them to be merged: lines in legend should have background fill that corresponds to the ribbon with the same name (and transparent for the "official tax" entry).
  • Lines in the legend differs by colour but they should differ by colour AND linetype.

Seems that I need to use scale_manual and guide_legend options, but all my attempts failed miserably.

Here is the code to create the plot. plotDumping is the function that draws the plot, updateData generates data frame for the plot and 'updateLabels' generates footnote for the plot.

library(ggplot2)
library(grid)
library(gridExtra)
library(scales)

max_waste_volume <- 2000 
Illegal_dumping_fine_P <- 300000
Illigal_landfilling_fine_P1 <- 500000
Fine_probability_k <- 0.5
Official_tax_Ta <- 600

# mwv = max_waste_volume
# P = Illegal_dumping_fine_P
# P1 = Illigal_landfilling_fine_P1
# k = Fine_probability_k
# Ta = Official_tax_Ta


updateData <- function(mwv, k, P1, P, Ta){

    # creates and(or) updates global data frame to provide data for the plot

    new_data <<- NULL
    new_data <<- as.data.frame(0:mwv)
    names(new_data) <<- 'V'
    new_data$IlD <<- k*P1/new_data$V
    new_data$IlD_fill <<- new_data$IlD
    new_data$IlD_fill[new_data$IlD_fill > Ta] <<- NA # we don't want ribbon to 
    new_data$IlL <<- Ta-k*P/new_data$V
}

updateLabels <- function(k, P1, P, Ta){

    ### creates footnote caption for the plot

    prob <- paste('Fining probability = ', k, sep = '')
    landfilling_fine <- paste('Illegal landfilling fine = ', P1, sep = '')
    dumping_fine <- paste('Illegal dumping fine = ', P, sep = '')
    tax <- paste('Official tax = ', Ta, sep = '')
    note <<- paste(prob, landfilling_fine, sep = '; ')
    note <<- paste(note, dumping_fine, sep = '; ')
    note <<- paste(note, tax, sep = '; ')
    note
}


plotDumping <- function(mwv, 
                        P,
                        P1,
                        k,
                        Ta){

  ### this function draws the plot

  # initialise plot data
  updateData(mwv, k, P1, P, Ta)
  updateLabels(k, P1, P, Ta)

  # draw the plot
  profit <- ggplot(data=new_data, aes(x = new_data$V)) +
    geom_ribbon(show_guide = T, alpha = 0.25, ymax = Ta, 
                aes(ymin = new_data$IlD_fill,
                    fill = "Illegal landfill owner's\nprofitable ratio\n")) +
    geom_ribbon(show_guide = F, alpha = 0.25, ymin = 0, 
                aes(ymax = new_data$IlL, 
                    fill = "Waste owner's\nprofitable ratio")) + 
    geom_line(data=new_data, 
              aes(y = new_data$IlD, col = "Illegal landfill owner's\nprofitable ratio\n"), 
              size = 1,
              linetype = 4) +
    geom_line(data=new_data, 
              aes(y = new_data$IlL, col = "Waste owner's\nprofitable ratio"), 
              size = 1,
              linetype = 5) + 
    geom_line(y = Ta, 
              aes(col = "Official tax"), 
              size = 1.5,
              linetype = 1)+ 
    xlim(c(0, max(new_data$V)))+
    ylim(c(0, Ta*1.5))+
    theme(axis.text.x = element_text(angle=0, hjust = 0),
          axis.title = element_text(face = 'bold', size = 14),
          title = element_text(face = 'bold', size = 16),
          legend.position = 'right',
          legend.title = element_blank(),
          legend.text = element_text(size = 12),
          legend.key.width = unit(1, 'cm'))+
    labs(title="Profitable ratio between the volume \nof illegally disposed waste \nand costs of illegal waste disposure",
         x="Waste volume, cubic meters",
         y="Cost per cubic meter, RUB")

   # add a footnote about paramaters used for the current plot
   profit <- arrangeGrob(profit, sub = textGrob(note, 
                                           x = 0, 
                                           hjust = -0.1, 
                                           vjust=0.1, 
                                           gp = gpar(fontface = "italic", fontsize = 12)))

 # show plot
 print(profit)
}

# draw the plot
plotDumping(max_waste_volume, 
                         Illegal_dumping_fine_P,
                         Illigal_landfilling_fine_P1,
                         Fine_probability_k,
                         Official_tax_Ta)
like image 708
SS_Rebelious Avatar asked May 05 '14 09:05

SS_Rebelious


People also ask

How do I change the legend text in ggplot2?

You can use the following syntax to change the legend labels in ggplot2: p + scale_fill_discrete(labels=c('label1', 'label2', 'label3', ...))

What does geom_ ribbon do?

For each x value, geom_ribbon() displays a y interval defined by ymin and ymax . geom_area() is a special case of geom_ribbon() , where the ymin is fixed to 0 and y is used instead of ymax .

How do I add a legend in ggplot2?

You can place the legend literally anywhere. To put it around the chart, use the legend. position option and specify top , right , bottom , or left . To put it inside the plot area, specify a vector of length 2, both values going between 0 and 1 and giving the x and y coordinates.

How do I get rid of the legend in ggplot2?

Example 1: Remove All Legends in ggplot2 We simply had to specify legend. position = “none” within the theme options to get rid of both legends.


1 Answers

One workaround in this situation would be to add geom_ribbon() also for the Official tax (using value Ta as ymax and ymin). This will make both legend with the same levels and they will be joined together. Then with scale_fill_manual() you can set fill value for Official tax to NA and then in legend for this level fill will be as background.

+ geom_ribbon(show_guide = F, alpha = 0.25, ymin = Ta,ymax=Ta, 
            aes(fill = "Official tax"))

+ scale_fill_manual(values=c("#F8766D",NA,"#00BFC4"))

enter image description here

P.S. Do not use the $ inside the aes() of ggplot() functions (use just column names). As you already wrote data=new_data all variables inside the aes() are looked for in this data frame.

like image 192
Didzis Elferts Avatar answered Oct 28 '22 13:10

Didzis Elferts