ggplot

时间:2016-08-27 20:08:00

标签: r ggplot2

我是ggplot2的初学者。所以,如果这个问题听起来太基本,我道歉。我很感激任何指导。我已经花了4个小时的时间来查看这个SO帖子R: Custom Legend for Multiple Layer ggplot以寻求指导,但最终无处可去。

目标:我希望能够将图例应用于用于不同图层的不同填充颜色。我正在做这个例子只是为了测试我对应用概念ggplot2概念的理解。

另外,我 NOT 想要改变形状类型;改变填充颜色很好 - 通过"填充"我并不是说我们可以改变颜色"。所以,如果你能纠正我的工作中的错误,我将不胜感激。

尝试1: 这是没有手动设置任何颜色的裸骨代码。

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

输出如下: enter image description here

现在,此图片存在一些问题:

问题1)显示"高mpg区域的青色矩形"失去了它的传奇。

问题2) ggplot尝试合并两个geom_point()图层中的图例,因此两个geom_point()的图例也会混合。

问题3) 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 = 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"))

这是输出: enter image description here 不幸的是,上面强调的一些问题仍然存在。有关订购的新问题。

问题#4:在我看来,ggplot2希望我按照图层设置的顺序提供颜色。即首先设置mtcars$vs填充的颜色,然后mtcars$cyl填充,最后设置青色的矩形。我能够通过修改代码来修复它:

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

所以,我有两个问题:

问题1:如何修复图例 - 我想要三个不同的图例 - 一个用于矩形填充(我称之为高mpg矩形),另一个用于填充{{1} }由geom_point()代表,最后一个代表mtcars$vs代表geom_point()

问题2:我的假设是关于颜色的排序是否正确(即上面讨论的问题#4)?我很怀疑,因为如果有很多因素,我们需要记住它们,然后按照绘制的图层对它们进行排序,最后还是记得按照每个mtcars$cyl图层的顺序手动应用调色板吗?

作为初学者,我花了很多时间在这上面,谷歌搜索到处都是。所以,我很感激你的善意指导。

3 个答案:

答案 0 :(得分:10)

(注意,我编辑了这个以便在几次来回之后进行清理 - 请参阅修订历史以了解更多我尝试过的内容。)

衡量标准实际上是为了显示一种类型的数据。一种方法是同时使用colfill,这可以使您获得至少2个传说。然后,您可以使用linetype添加override.aes并稍微破解它。值得注意的是,我认为这可能(通常)会引发更多问题,而不是解决问题。如果你迫切需要这样做,你可以(例如下面的例子)。但是,如果我可以说服你:我恳求你尽可能使用这种方法。映射到不同的内容(例如shapelinetype)可能会减少混淆。我在下面给出一个例子。

此外,在手动设置颜色或填充时,最好使用palette的命名向量来确保颜色与您想要的颜色相匹配。如果不是,则匹配按因子级别的顺序发生。

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)))

enter image description here

以下是我认为几乎适用于所有用例的情节:

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

enter image description here

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

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)))

因为我显然不能单独留下这一点 - 这是另一种方法,只使用填充美学,然后为单个图层制作单独的图例,并使用cowplot松散地将它们拼接在一起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))

enter image description here

正如您所看到的,结果几乎与我演示如何执行此操作的 first 方式相同,但现在不使用任何其他美学。我仍然不明白为什么你认为这种区别是重要的,但至少现在有另一种方法可以给猫皮肤。我可以使用这种方法的一般性(例如,当多个绘图共享颜色/符号/线型美学的混合并且您想要使用单个图例时)但我认为在此处使用它没有任何价值。

答案 1 :(得分:0)

现在有了很棒的ggnewscale软件包,可以通过简单的方式完成此操作。

答案 2 :(得分:-1)

您还可以使用align_plots中的ggdrawcowplot函数分层多个图来实现此目的。这是我用于将散射(离散色标)放到光栅上的解决方案(连续色标)。请参阅以下链接中的插图。

https://www.rdocumentation.org/packages/cowplot/versions/0.9.2/topics/align_plots