2017-10-11 513 views
1

我在修改ggplot2图中的图例时遇到了一些问题。具体而言,我想创建两个传说而不是一个,并更改里面的名字。为一个ggplot2图创建两个图例并修改它们

我想绘制三条曲线连同两条垂直线,从x轴到第一条曲线。我使用的代码如下:

# generate data 

X1 <- as.data.frame(matrix(nrow = 10, ncol = 2)) 
colnames(X1) <- c("Weight", "Height") 
X1$Weight <- seq(1:10) 
X1$Height <- c(2, 3, 3.5, 4, 3.8, 5, 6.1, 5.4, 7, 7.1) 

X2 <- as.data.frame(matrix(nrow = 10, ncol = 2)) 
colnames(X2) <- c("Weight", "Height") 
X2$Weight <- c(seq(1:8), NA, NA) 
X2$Height <- c(4, 3.4, 3.1, 6, 5.4, 6, 6.3, 7.5, NA, NA) 

X3 <- as.data.frame(matrix(nrow = 10, ncol = 2)) 
colnames(X3) <- c("Weight", "Height") 
X3$Weight <- c(seq(1:10)) 
X3$Height <- c(7, 6.9, 6.8, 6.1, 7, 7.5, 7.8, 9, 9.2, 9.1) 

# create plot 

require(ggplot2) 
mycurve <- qplot(Weight, Height, data = X1, geom = "line", color = "X1", 
      main = "Plot", xlab = "Weight [kg]", ylab = "Height [m]", 
      xlim = range(X1$Weight)) 

mycurve + 
    geom_line(aes(X2$Weight, X2$Height, color = "X2"), 
      linetype = "twodash", na.rm = TRUE) + 
    geom_line(aes(X3$Weight, X3$Height, color = "X3"), 
      linetype = "dotted", na.rm = TRUE) + 
    geom_segment(aes(x = 5, y = 0, color = "Y1", xend = 5, yend = X1["5", 2]), 
       linetype="longdash") + 
    geom_segment(aes(x = 7, y = 0, color = "Y2", xend = 7, yend = X1["7", 2]), 
       linetype="longdash") + 
    scale_color_manual(values=c("X1" = "black", "X2" = "darkseagreen4", 
           "X3" = "darkred", "Y1"="green2", "Y2"="blue")) + 
    theme_bw() 

它给了我这样的输出:

Output plot

现在我想改变的传说。我想有两种传说:

  • 一个名为“对象”,给我“Object1”(X1),“对象2”(X2)和“Object3”(X3)
  • 另一种名为“线“并且包含”Line1“(Y1)和”Line2“(Y2)

此外,我希望”对象“具有以下顺序:”Object2“,”Object1“,”Object3“。

我很感谢任何帮助解决这个问题!

回答

0

我建议将您的数据合并到一个数据框中。它是传递给ggplot()整洁:

# combine data 
df <- rbind(X1, X2, X3) 
df$Group <- rep(c("Object1", "Object2", "Object3"), each = 10) 

df <- rbind(df, 
      data.frame(Weight = 5, 
         Height = c(0, X1["5", 2]), 
         Group = "Line1"), 
      data.frame(Weight = 7, 
         Height = c(0, X1["7", 2]), 
         Group = "Line2")) 

在ggplot,我们有一个设计规模每一个类型的传说,所以具有线条颜色两种传说是不是顺其自然。文章here讨论了一些方法。我利用了2nd solution的:

# add legend groupings as unused factor levels 
# also specify legend order 
df$Group <- factor(df$Group, levels = c("Object", 
             "Object2", "Object1", "Object3", 
             " ", 
             "Lines", 
             "Line1", "Line2")) 

另外,我建议使用ggplot而非qplot。正如包的文件指出,qplot被设计成与底座plot函数的语法一致性一个方便的包装,但ggplot在处理较复杂的情节要求更好:

p <- ggplot(df, 
     aes(x = Weight, y = Height, 
      group = Group, linetype = Group, color = Group)) + 
    geom_line() + 
    scale_linetype_manual(values = c(# actual line types used in the plot 
            "Object1" = "solid", 
            "Object2" = "twodash", 
            "Object3" = "dotted", 
            "Line1" = "longdash", 
            "Line2" = "longdash", 
            # placeholder values for legend titles 
            "Object" = "solid", "Lines" = "solid", " " = "solid"), 
         drop = F) + 
    scale_color_manual(values = c(# actual line types used in the plot 
           "Object1" = "black", 
           "Object2" = "darkseagreen4", 
           "Object3" = "darkred", 
           "Line1" = "green2", 
           "Line2" = "blue", 
           # placeholder values for legend titles 
           "Object" = "white", "Lines" = "white", " " = "white"), 
        drop = F) + 
    labs(title = "Plot", x = "Weight [kg]", y = "Height [m]") + 
    theme_bw() + 
    theme(legend.title = element_blank()) 

p 

plot

编辑到包括更改个人图例标签:

我们可以对个别图例标签进行进一步更改,以使伪图例标题与其他“正常” ' 标签。由于ggplot的传奇不是设计来处理这种使用情况下,我们可以通过打开图(一GGPLOT2对象)到GROB对象(图形对象基本上是一个嵌套列表)破解它,&进行修改有:

# convert original plot (saved as p) into a grob 
g <- ggplotGrob(p) 

找到与图例标签对应的嵌套grob(有些方法可以使用代码通过关键字进行搜索,但对于一次性使用案例,我发现通过列表更容易查看......):

> g # grob 15 (named guide-box) contains the legend 
TableGrob (10 x 9) "layout": 18 grobs 
    z   cells  name         grob 
1 0 (1-10, 1- 9) background  rect[plot.background..rect.174] 
2 5 (5- 5, 3- 3)  spacer       zeroGrob[NULL] 
3 7 (6- 6, 3- 3)  axis-l absoluteGrob[GRID.absoluteGrob.124] 
4 3 (7- 7, 3- 3)  spacer       zeroGrob[NULL] 
5 6 (5- 5, 4- 4)  axis-t       zeroGrob[NULL] 
6 1 (6- 6, 4- 4)  panel    gTree[panel-1.gTree.104] 
7 9 (7- 7, 4- 4)  axis-b absoluteGrob[GRID.absoluteGrob.117] 
8 4 (5- 5, 5- 5)  spacer       zeroGrob[NULL] 
9 8 (6- 6, 5- 5)  axis-r       zeroGrob[NULL] 
10 2 (7- 7, 5- 5)  spacer       zeroGrob[NULL] 
11 10 (4- 4, 4- 4)  xlab-t       zeroGrob[NULL] 
12 11 (8- 8, 4- 4)  xlab-b titleGrob[axis.title.x..titleGrob.107] 
13 12 (6- 6, 2- 2)  ylab-l titleGrob[axis.title.y..titleGrob.110] 
14 13 (6- 6, 6- 6)  ylab-r       zeroGrob[NULL] 
15 14 (6- 6, 8- 8) guide-box      gtable[guide-box] 
16 15 (3- 3, 4- 4) subtitle zeroGrob[plot.subtitle..zeroGrob.171] 
17 16 (2- 2, 4- 4)  title titleGrob[plot.title..titleGrob.170] 
18 17 (9- 9, 4- 4) caption zeroGrob[plot.caption..zeroGrob.172] 

> g$grobs[[15]] # grob 1 (named guides) contains the actual legend table 
TableGrob (5 x 5) "guide-box": 2 grobs 
            z  cells     name   grob 
99_ff1a4629bd4c693e1303e4eecfb18bd2 1 (3-3,3-3)    guides gtable[layout] 
            0 (2-4,2-4) legend.box.background zeroGrob[NULL] 

> g$grobs[[15]]$grobs[[1]] # grobs 19-25 contain the legend labels 
TableGrob (12 x 6) "layout": 26 grobs 
    z   cells  name        grob 
1 1 (1-12, 1- 6) background rect[legend.background..rect.167] 
2 2 (2- 2, 2- 5)  title zeroGrob[guide.title.zeroGrob.125] 
3 3 (4- 4, 2- 2) key-3-1-bg   rect[legend.key..rect.143] 
4 4 (4- 4, 2- 2) key-3-1-1  segments[GRID.segments.144] 
5 5 (5- 5, 2- 2) key-4-1-bg   rect[legend.key..rect.146] 
6 6 (5- 5, 2- 2) key-4-1-1  segments[GRID.segments.147] 
7 7 (6- 6, 2- 2) key-5-1-bg   rect[legend.key..rect.149] 
8 8 (6- 6, 2- 2) key-5-1-1  segments[GRID.segments.150] 
9 9 (7- 7, 2- 2) key-6-1-bg   rect[legend.key..rect.152] 
10 10 (7- 7, 2- 2) key-6-1-1  segments[GRID.segments.153] 
11 11 (8- 8, 2- 2) key-7-1-bg   rect[legend.key..rect.155] 
12 12 (8- 8, 2- 2) key-7-1-1  segments[GRID.segments.156] 
13 13 (9- 9, 2- 2) key-8-1-bg   rect[legend.key..rect.158] 
14 14 (9- 9, 2- 2) key-8-1-1  segments[GRID.segments.159] 
15 15 (10-10, 2- 2) key-9-1-bg   rect[legend.key..rect.161] 
16 16 (10-10, 2- 2) key-9-1-1  segments[GRID.segments.162] 
17 17 (11-11, 2- 2) key-10-1-bg   rect[legend.key..rect.164] 
18 18 (11-11, 2- 2) key-10-1-1  segments[GRID.segments.165] 
19 19 (4- 4, 4- 4) label-3-3   text[guide.label.text.127] 
20 20 (5- 5, 4- 4) label-4-3   text[guide.label.text.129] 
21 21 (6- 6, 4- 4) label-5-3   text[guide.label.text.131] 
22 22 (7- 7, 4- 4) label-6-3   text[guide.label.text.133] 
23 23 (8- 8, 4- 4) label-7-3   text[guide.label.text.135] 
24 24 (9- 9, 4- 4) label-8-3   text[guide.label.text.137] 
25 25 (10-10, 4- 4) label-9-3   text[guide.label.text.139] 
26 26 (11-11, 4- 4) label-10-3   text[guide.label.text.141] 

我们可以由此找到对应于 “对象” & “线” 的grobs。它们是:

g$grobs[[15]]$grobs[[1]]$grobs[[19]] # label for "Object" 
g$grobs[[15]]$grobs[[1]]$grobs[[24]] # label for "Lines" 

> str(g$grobs[[15]]$grobs[[1]]$grobs[[19]]) # examine a label 
List of 11 
$ label  : chr "Object" 
$ x   :Class 'unit' atomic [1:1] 0 
    .. ..- attr(*, "valid.unit")= int 0 
    .. ..- attr(*, "unit")= chr "npc" 
$ y   :Class 'unit' atomic [1:1] 0.5 
    .. ..- attr(*, "valid.unit")= int 0 
    .. ..- attr(*, "unit")= chr "npc" 
$ just   : chr "centre" 
$ hjust  : num 0 
$ vjust  : num 0.5 
$ rot   : num 0 
$ check.overlap: logi FALSE 
$ name   : chr "guide.label.text.214" 
$ gp   :List of 5 
    ..$ fontsize : num 8.8 
    ..$ col  : chr "black" 
    ..$ fontfamily: chr "" 
    ..$ lineheight: num 0.9 
    ..$ font  : Named int 1 
    .. ..- attr(*, "names")= chr "plain" 
    ..- attr(*, "class")= chr "gpar" 
$ vp   : NULL 
- attr(*, "class")= chr [1:3] "text" "grob" "gDesc" 

我们可以看到,格式下拍摄.$gp(图形参数列表,请参阅here更多信息)。我们可以修改的列表,&取代他们在原始列表中每个标签:

# make changes to format (examples of various things that can be changed) 
gp.new <- list(fontsize = 10, # increase font size 
       col = "red", # change font color 
       font = 2L)  # change from plain (1L) to bold (2L) 

for(i in c(19, 24)){ 
    gp <- g$grobs[[15]]$grobs[[1]]$grobs[[i]]$gp 

    ind1 <- match(names(gp.new), names(gp)) 
    ind2 <- match(names(gp), names(gp.new)) 
    ind2 <- ind2[!is.na(ind2)] 

    g$grobs[[15]]$grobs[[1]]$grobs[[i]]$gp <- replace(x = gp, 
                list = ind1, 
                values = gp.new[ind2]) 
} 
rm(gp, gp.new, ind1, ind2, i) 

叠加的结果。需要注意的是绘制一个GROB,你需要使用grid.draw()从格包:

grid::grid.draw(g) 

plot2

+0

太谢谢你了。它完美的工作,你解释得很好。 还有一件事:有没有办法增加只有(!)“Object”和“Lines”的字体大小? – Wruke

+0

@Wruke用修改过的图例标签更新了我的答案。 –

相关问题