如何结合修改ggplot2图例中的色带和线条?

5
我对以下图例有几个问题: enter image description here
  • 彩带和线分别放在两个图例中,但我想合并它们: 图例中的线应该有背景填充,填充颜色与同名的彩带相同 (对于"official tax"项应该是透明的)。
  • 图例中的线看起来只有颜色不同,但它们应该通过颜色和线条类型来区分。
看起来我需要使用 `scale_manual` 和 `guide_legend` 选项,但我的所有尝试都失败了。
以下是创建此图表所需的代码。`plotDumping` 是绘制图表的函数,`updateData` 生成图表的数据框,'updateLabels' 为图表生成脚注。
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)
2个回答

3
在这种情况下,一个解决方法是在 Official tax 中添加geom_ribbon()(使用值Ta作为ymaxymin),这将使两个图例具有相同的级别并且它们将连接在一起。然后使用scale_fill_manual(),你可以将Official tax的填充值设置为NA,然后在该级别的图例中,填充将作为背景。
+ geom_ribbon(show_guide = F, alpha = 0.25, ymin = Ta,ymax=Ta, 
            aes(fill = "Official tax"))

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

输入图像描述

注意,在ggplot()函数的aes()中不要使用$(只需使用列名)。因为已经写了data=new_data,所以在aes()内寻找的所有变量都在该数据框中。


不错的解决方法,谢谢。我必须在aes内部使用$,否则我的函数将无法与manipulation库正确地工作。 - SS_Rebelious

2

如果您将线型放在 aes 函数中,您可以使用您的版本来获取正确的线型。但是,这种方式会使您的代码变得更加繁琐。在调用 ggplot 之前考虑重新整理数据。然后您就不必担心图例了。

# 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"

现在绘图命令变得更加简单和透明:
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")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接