Question

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)
Was it helpful?

Solution 2

You can use your version to also get the correct linetype, if you put the linetype insidt the aes function. However, your code becomes even more cumbersome that way. Consider reshaping your data before calling ggplot. Then you don't have to worry about the legend at all.

# reshape data ...
new_data$Ta <- Ta
new_data$zero <- 0
require(reshape2)
dta <- melt(new_data, id.vars="V", measure.vars=c("IlD", "IlL", "Ta"))
dta.lower <- melt(new_data, id.vars="V", measure.vars=c("IlD_fill", "zero", "Ta"))
dta.upper <- melt(new_data, id.vars="V", measure.vars=c("Ta", "IlL", "Ta"))
dta <- cbind(dta, lower=dta.lower$value, upper=dta.upper$value)
dta$name <- factor(NA, levels=c("Illegal landfill owner's\nprofitable ratio\n",
                                "Waste owner's\nprofitable ratio", 
                                "Official tax"))
dta$name[dta$variable=="IlD"] <- "Illegal landfill owner's\nprofitable ratio\n"
dta$name[dta$variable=="IlL"] <- "Waste owner's\nprofitable ratio"
dta$name[dta$variable=="Ta"] <- "Official tax"

Now tha plotting command becomes much easier and more transparent:

ggplot(dta, aes(x=V, y=value, ymin=lower, ymax=upper, 
                color=name, fill=name, linetype=name)) +
  geom_line(size=1.2) + ylim(c(0, Ta*1.5)) +
  geom_ribbon(alpha=.25, linetype=0) +
  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(2, 'cm'))+
  scale_linetype_manual(values=c(4, 5, 1)) +
  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")

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top