ggplot中的多个填充的图例 [英] Legends for multiple fills in ggplot

查看:201
本文介绍了ggplot中的多个填充的图例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 ggplot2 的初学者。所以,如果这个问题听起来太简单,我很抱歉。我会很感激任何指导。我已经花了4个小时在这个,看着这个SO线程



现在,这张图片存在一些问题:



问题1)显示高mpg区域的青色长方形已经失去了它的图例。

问题2) ggplot tr结合两个 geom_point()图层中的图例,并作为结果为两个 geom_point()

第3期) 使用的默认颜色paleltte使得 ggplot2 我的眼睛的颜色不可区分。

因此,我采取了手动设置颜色,即开始固定#3以上。

  ggplot(mtcars,aes(disp,mpg))+ 
geom_point(aes(fill = factor(vs)),shape = 23,size = 8,alpha = 0.4)+
geom_point(aes(fill = factor(cyl)),shape = 21,size = 2)+
geom_rect(aes(xmin = min(disp)-5, ymax = max(mpg)+ 2,fill =cyan),
xmax =平均值(范围(mtcars $ disp)),ymin = 25,alpha = 0.02)+
scale_fill_manual(values = c (绿色,蓝色,黑色,青色,红色,橙色),
标签= c(四档,六档,八档输入:













$ b
不幸的是,上面强调的一些问题仍然存在。有关于订购的新问题。



问题#4:在我看来, ggplot2 期望我提供颜色按顺序设置图层。即首先将颜色设置为 mtcars $ vs 填充,然后 mtcars $ cyl 填充,最后使用青色填充矩形。我可以通过修改代码来修复它:

  ggplot(mtcars,aes(disp,mpg))+ 
geom_point(aes(fill = factor(cyl)),shape = 21,size = 2,aes(fill = factor(vs)),shape = 23,size = 8,alpha = 0.4) )+
geom_rect(aes(xmin = min(disp)-5,ymax = max(mpg)+ 2,fill =cyan),
xmax = mean(mtcars $ disp)) ,ymin = 25,alpha = 0.02)+
scale_fill_manual(values = c(red,orange,green,blue,black,cyan),
labels = c(0,1,4档,6档,8档,高mpg))#改变订单

所以,我有两个问题:

问题1:修正传说 - 我想要三个不同的传说 - 一个用于矩形填充(我称之为高mpg矩形),另一个用于填充 geom_point(),由 mtcars $ vs ,最后一个为 geom_point()的填充 mtcars $ cyl



问题2:我的假设是根据图层的颜色排序是否正确。上面讨论的问题#4)?我怀疑,因为如果有很多因素 - 我们是否需要记住它们,然后根据绘制的图层对它们进行排序,最后记住按照 geom _ *( )图层被创建?



作为初学者,我花了很多时间在这个网站上搜索每个地方。所以,我会很感激你的指导。

解决方案

即将到来 - 请参阅我尝试过的更多修订历史记录。)



这些比例尺实际上意味着显示一种类型的数据。一种方法是使用 col fill ,这可以让你至少有2个传说。然后你可以添加 linetype 并使用 override.aes 来修改它。值得注意的是,我认为这可能(通常)会导致更多的问题而不是解决问题。如果你迫切需要这样做,你可以(下面的例子)。不过,如果我能说服你:我恳求你不要尽可能使用这种方法。映射到不同的东西(例如 shape linetype )很可能会导致混淆。我给出了一个下面的例子。



另外,当手动设置颜色或填充时,对调色板使用命名向量总是一个好主意确保颜色符合您的要求。

  ggplot(mtcars,aes(x = disp 
)如果没有,则匹配按照因子级别的顺序发生。 ,y = mpg))+
##地区为高mpg
geom_rect(aes(linetype =High MPG)
,xmin = min(mtcars $ disp)-5
,ymax = max(mtcars $ mpg)+ 2
,fill =cyan
,xmax =平均值(范围(mtcars $ disp))
,ymin = 25
,alpha = 0.02
,col =black)+
##测试差异区域
geom_rect(aes(linetype =Other Region)
,xmin = 300
,xmax = 400
,ymax = 30
,ymin = 25
,fill =yellow
,alpha = 0.02
,col =black )+
geom_point(aes(col =因子(cyl)),形状= 19(aes(col =因子(cyl)),形状= 19 ,size = 2)+
scale_color_manual(values = c(4=red
,6=orange
,8=green)
,name =Cylinders)+
scale_fill_manual(values = c(0=blue
,1=black
,cyan=cyan)
,name =V / S
,labels = c(0? ,1,High MPG))+
scale_linetype_manual(values = c(High MPG= 0
,Other Region= 0)
,name =Region
,guide = guide_legend(override.aes = list(fill = c(cyan,yellow)
,alpha = .4)))



这里是情节我认为对于几乎所有用例都会更好:

  ggplot(mtcars,aes(x = disp 
$ y

$ b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b,ymax = max(mtcars $ mpg)+ 2
,fill = NA
,xmax =平均值(范围(mtcars $ disp))
,ymin = 25
, (aes(linetype =Other Region)
,xmin = 300
,xmax = 400
,ymax = 30
,ymin = 25
,fill = NA
,col =black)+
geom_point(aes(col = factor(cyl)
),shape = factor(vs))
,size = 3)+
scale_color_brewer(name =Cylinders
,palette =Set1)+
scale_shape(name = V / S)+
scale_linetype_manual(值= c(High MPG=dotted
,Other Region=dashed)
,name =Region)



出于某种原因,您坚持使用。这是一种使正好与此答案中的第一个图相同的方法,但使用 fill 作为每个图层的美学。如果这不是你所坚持的,那么我仍然不知道你在找什么。

  ggplot (aes(linetype =High MPG)
,xmin(mtcars,aes(x = disp
,y = mpg))+
##高地区的地区
geom_rect = min(mtcars $ disp)-5
,ymax = max(mtcars $ mpg)+ 2
,fill =cyan
,xmax = mean(范围(mtcars $ disp))
,ymin = 25
,alpha = 0.02
,col =black)+
##测试差异区域
geom_rect(aes(linetype =Other Region )
,xmin = 300
,xmax = 400
,ymax = 30
,ymin = 25
,fill =yellow
,alpha = 0.02
,col =black)+
geom_point(aes(fill = factor(vs)),shape = 23,size = 8,alpha = 0.4)+
geom_point(aes (col =4)
,data = mtcars [mtcars $ cyl == 4 ,]
,shape = 21
,size = 2
,fill =red)+
geom_point(aes(col =6)
,data = mtcars [mtcars $ cyl == 6,]
,shape = 21
,size = 2
,fill =orange)+
geom_point(aes(col = 8)
,data = mtcars [mtcars $ cyl == 8,]
,shape = 21
,size = 2
,fill =green)+
scale_color_manual(values = c(4= NA
,6= NA
,8= NA)
,name =Cylinders
,guide = guide_legend(override.aes = list(fill = c(red,orange,green))))+
scale_fill_manual(values = c(0=blue
,1=黑色
,青色=青色)
,名称=V / S
,标签= c(0,1,高级MPG))+
scale_linetype_manual(values = c(High MPG= 0
,Other Region= 0)
,name =Region
,guide = guide_legend(override.aes = list(fill = c(cyan,yellow)
,alpha = .4)))
$ / pre

因为我显然不能离开这一点 - 这是另一种使用填充美学的方法,然后使用 cowplot 将这些单独图层的单独图例拼接在一起,松散地跟在



正如您所看到的,结果几乎与<第一种方法,我演示了如何做到这一点,但现在不使用任何其他美学。我仍然不明白你为什么认为这种区分很重要,但至少现在有另一种方法来剥皮猫。我可以使用这种方法的一般性(例如,当多个地块共享颜色/符号/线型美学的组合,并且您想使用单个图例时),但在这里使用它看不出任何价值。


I am a beginner in ggplot2. So, I apologize if this question sounds too basic. I'd appreciate any guidance. I've spent 4 hours on this and looked at this SO thread R: Custom Legend for Multiple Layer ggplot for guidance, but ended up nowhere.

Objective: I want to be able to apply legend to different fill colors used for different layers. I am doing this example just for the sake of testing my understanding of applying concepts ggplot2 concepts.

Also, I do NOT want to change the shape type; changing fill colors is fine--by "fill" I do not mean that we could change "color". So, I would appreciate if you can correct my mistakes in my work.

Try 1: Here's the bare bones code without any colors set manually.

ggplot(mtcars, aes(disp,mpg)) +
geom_point(aes(fill = factor(vs)),shape = 23, size = 8, alpha = 0.4) +
geom_point (aes(fill = factor(cyl)),shape = 21, size = 2) +
geom_rect(aes(xmin = min(disp)-5, ymax = max(mpg) + 2,fill = "cyan"), 
xmax = mean(range(mtcars$disp)),ymin = 25, alpha = 0.02) ##region for high mpg

The output looks like this:

Now, there are a few problems with this image:

Issue 1) The cyan rectangle that shows "high mpg areas" has lost its legend.

Issue 2) ggplot tries to combine the legend from the two geom_point() layers and as a result the legend for the two geom_point() are also mixed.

Issue 3) The default color paleltte used by ggplot2 makes the colors non-distinguishable for my eyes.

So, I took a stab at manually setting the colors i.e.start with fixing #3 above.

ggplot(mtcars, aes(disp,mpg)) + 
       geom_point(aes(fill = factor(vs)),shape = 23, size = 8, alpha = 0.4)+
       geom_point(aes(fill = factor(cyl)),shape = 21, size = 2) +
       geom_rect(aes(xmin = min(disp)-5, ymax = max(mpg) + 2,fill = "cyan"),
                 xmax = mean(range(mtcars$disp)),ymin = 25, alpha = 0.02) + 
     scale_fill_manual(values = c("green","blue", "black", "cyan", "red", "orange"), 
labels=c("4 gears","6 gears","8 gears","High mpg","0","1"))

Here's the output: Unfortunately, some of the problems highlighted above persist. There is new issue about ordering.

Issue#4: It seems to me that ggplot2 expects me to provide colors in the order the layers were set. i.e. first set the color for mtcars$vs fill, then mtcars$cyl fill and finally the rectangle with cyan color. I was able to fix it by modifying the code to:

ggplot(mtcars, aes(disp,mpg)) + 
       geom_point(aes(fill = factor(vs)),shape = 23, size = 8, alpha = 0.4) +
       geom_point(aes(fill = factor(cyl)),shape = 21, size = 2) +
       geom_rect(aes(xmin = min(disp)-5, ymax = max(mpg) + 2,fill = "cyan"),
                 xmax = mean(range(mtcars$disp)),ymin = 25, alpha = 0.02) + 
     scale_fill_manual(values = c("red", "orange", "green", "blue", "black", "cyan"), 
labels=c("0","1","4 gears","6 gears","8 gears","High mpg")) #changed the order

So, I have two questions:

Question 1: How do I fix the legends--I want three different legends--one for rectangle fill (which I call high mpg rectangle), another one for fill for geom_point() represented by mtcars$vs and the last one for fill for geom_point()represented by mtcars$cyl

Question2: Is my hypothesis about ordering of colors as per the layers correct (i.e. Issue#4 discussed above)? I am doubtful because what if there are a lot of factors--are we required to memorize them, then order them as per the layers drawn and finally remember to apply color palette manually in the order each geom_*() layers are created?

As a beginner, I have spent a lot many hours on this, googling everywhere. So, I'd appreciate your kind guidance.

解决方案

(Note, I edited this to clean it up after a few back and forths -- see the revision history for more of what I tried.)

The scales really are meant to show one type of data. One approach is to use both col and fill, that can get you to at least 2 legends. You can then add linetype and hack it a bit using override.aes. Of note, I think this is likely to (generally) lead you to more problems than it will solve. If you desperately need to do this, you can (example below). However, if I can convince you: I implore you not to use this approach if at all possible. Mapping to different things (e.g. shape and linetype) is likely to lead to less confusion. I give an example of that below.

Also, when setting colors or fills manually, it is always a good idea to use named vectors for palette that ensure the colors match what you want. If not, the matches happen in order of the factor levels.

ggplot(mtcars, aes(x = disp
                   , y = mpg)) +
  ##region for high mpg 
  geom_rect(aes(linetype = "High MPG")
            , xmin = min(mtcars$disp)-5
            , ymax = max(mtcars$mpg) + 2
            , fill = "cyan"
            , xmax = mean(range(mtcars$disp))
            , ymin = 25
            , alpha = 0.02
            , col = "black") + 
  ## test diff region
  geom_rect(aes(linetype = "Other Region")
            , xmin = 300
            , xmax = 400
            , ymax = 30
            , ymin = 25
            , fill = "yellow"
            , alpha = 0.02
            , col = "black") + 
  geom_point(aes(fill = factor(vs)),shape = 23, size = 8, alpha = 0.4) +
  geom_point (aes(col = factor(cyl)),shape = 19, size = 2) +
  scale_color_manual(values = c("4" = "red"
                                , "6" = "orange"
                                , "8" = "green")
                     , name = "Cylinders") +
  scale_fill_manual(values = c("0" = "blue"
                               , "1" = "black"
                               , "cyan" = "cyan")
                    , name = "V/S"
                    , labels = c("0?", "1?", "High MPG")) +
  scale_linetype_manual(values = c("High MPG" = 0
                                   , "Other Region" = 0)
                        , name = "Region"
                        , guide = guide_legend(override.aes = list(fill = c("cyan", "yellow")
                                                                       , alpha = .4)))

Here is the plot I think will work better for nearly all use cases:

ggplot(mtcars, aes(x = disp
                   , y = mpg)) +
  ##region for high mpg 
  geom_rect(aes(linetype = "High MPG")
            , xmin = min(mtcars$disp)-5
            , ymax = max(mtcars$mpg) + 2
            , fill = NA
            , xmax = mean(range(mtcars$disp))
            , ymin = 25
            , col = "black") + 
  ## test diff region
  geom_rect(aes(linetype = "Other Region")
            , xmin = 300
            , xmax = 400
            , ymax = 30
            , ymin = 25
            , fill = NA
            , col = "black") +
  geom_point(aes(col = factor(cyl)
                 , shape = factor(vs))
             , size = 3) +
  scale_color_brewer(name = "Cylinders"
                     , palette = "Set1") +
  scale_shape(name = "V/S") +
  scale_linetype_manual(values = c("High MPG" = "dotted"
                                   , "Other Region" = "dashed")
                        , name = "Region")

For some reason, you insist on using fill. Here is an approach that makes exactly the same plot as the first one in this answer, but uses fill as the aesthetic for each of the layers. If this isn't what you are insisting on, then I still have no idea what it is you are looking for.

ggplot(mtcars, aes(x = disp
                   , y = mpg)) +
  ##region for high mpg 
  geom_rect(aes(linetype = "High MPG")
            , xmin = min(mtcars$disp)-5
            , ymax = max(mtcars$mpg) + 2
            , fill = "cyan"
            , xmax = mean(range(mtcars$disp))
            , ymin = 25
            , alpha = 0.02
            , col = "black") + 
  ## test diff region
  geom_rect(aes(linetype = "Other Region")
            , xmin = 300
            , xmax = 400
            , ymax = 30
            , ymin = 25
            , fill = "yellow"
            , alpha = 0.02
            , col = "black") + 
  geom_point(aes(fill = factor(vs)),shape = 23, size = 8, alpha = 0.4) +
  geom_point (aes(col = "4")
              , data = mtcars[mtcars$cyl == 4, ]
              , shape = 21
              , size = 2
              , fill = "red") +
  geom_point (aes(col = "6")
              , data = mtcars[mtcars$cyl == 6, ]
              , shape = 21
              , size = 2
              , fill = "orange") +
  geom_point (aes(col = "8")
              , data = mtcars[mtcars$cyl == 8, ]
              , shape = 21
              , size = 2
              , fill = "green") +
  scale_color_manual(values = c("4" = NA
                                , "6" = NA
                                , "8" = NA)
                     , name = "Cylinders"
                     , guide = guide_legend(override.aes = list(fill = c("red","orange","green")))) +
  scale_fill_manual(values = c("0" = "blue"
                               , "1" = "black"
                               , "cyan" = "cyan")
                    , name = "V/S"
                    , labels = c("0?", "1?", "High MPG")) +
  scale_linetype_manual(values = c("High MPG" = 0
                                   , "Other Region" = 0)
                        , name = "Region"
                        , guide = guide_legend(override.aes = list(fill = c("cyan", "yellow")
                                                                   , alpha = .4)))

Because I apparently can't leave this alone -- here is another approach using just fill for the aesthetic, then making separate legends for the single layers and stitching it all back together using cowplot loosely following this tutorial.

library(cowplot)
library(dplyr)

theme_set(theme_minimal())

allScales <-
  c("4" = "red"
    , "6" = "orange"
    , "8" = "green"
    , "0" = "blue"
    , "1" = "black"
    , "High MPG" = "cyan"
    , "Other Region" = "yellow")

mainPlot <-
  ggplot(mtcars, aes(x = disp
                     , y = mpg)) +
  ##region for high mpg 
  geom_rect(aes(fill = "High MPG")
            , xmin = min(mtcars$disp)-5
            , ymax = max(mtcars$mpg) + 2
            , xmax = mean(range(mtcars$disp))
            , ymin = 25
            , alpha = 0.02) + 
  ## test diff region
  geom_rect(aes(fill = "Other Region")
            , xmin = 300
            , xmax = 400
            , ymax = 30
            , ymin = 25
            , alpha = 0.02) + 
  geom_point(aes(fill = factor(vs)),shape = 23, size = 8, alpha = 0.4) +
  geom_point (aes(fill = factor(cyl)),shape = 21, size = 2) +
  scale_fill_manual(values = allScales)

vsLeg <-
  (ggplot(mtcars, aes(x = disp
                      , y = mpg)) +
     geom_point(aes(fill = factor(vs)),shape = 23, size = 8, alpha = 0.4) +
     scale_fill_manual(values = allScales
                       , name = "VS")
  ) %>%
  ggplotGrob %>%
  {.$grobs[[which(sapply(.$grobs, function(x) {x$name}) == "guide-box")]]}



cylLeg <-
  (ggplot(mtcars, aes(x = disp
                      , y = mpg)) +
     geom_point (aes(fill = factor(cyl)),shape = 21, size = 2) +
     scale_fill_manual(values = allScales
                       , name = "Cylinders")
  ) %>%
  ggplotGrob %>%
  {.$grobs[[which(sapply(.$grobs, function(x) {x$name}) == "guide-box")]]}


regionLeg <-
  (ggplot(mtcars, aes(x = disp
                      , y = mpg)) +
     geom_rect(aes(fill = "High MPG")
               , xmin = min(mtcars$disp)-5
               , ymax = max(mtcars$mpg) + 2
               , xmax = mean(range(mtcars$disp))
               , ymin = 25
               , alpha = 0.02) + 
     ## test diff region
     geom_rect(aes(fill = "Other Region")
               , xmin = 300
               , xmax = 400
               , ymax = 30
               , ymin = 25
               , alpha = 0.02) + 
     scale_fill_manual(values = allScales
                       , name = "Region"
                       , guide = guide_legend(override.aes = list(alpha = 0.4)))
  ) %>%
  ggplotGrob %>%
  {.$grobs[[which(sapply(.$grobs, function(x) {x$name}) == "guide-box")]]}


legendColumn <-
  plot_grid(
    # To make space at the top
    vsLeg + theme(legend.position = "none")
    # Plot the legends
    , vsLeg, regionLeg, cylLeg
    # To make space at the bottom
    , vsLeg + theme(legend.position = "none")
    , ncol = 1
    , align = "v")

plot_grid(mainPlot +
            theme(legend.position = "none")
          , legendColumn
          , rel_widths = c(1,.25))

As you can see, the outcome is nearly identical to the first way that I demonstrated how to do this, but now does not use any other aesthetics. I still don't understand why you think that distinction is important, but at least there is now another way to skin a cat. I can uses for the generalities of this approach (e.g., when multiple plots share a mix of color/symbol/linetype aesthetics and you want to use a single legend) but I see no value in using it here.

这篇关于ggplot中的多个填充的图例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆