2017-10-11 522 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用修改過的圖例標籤更新了我的答案。 –

相關問題