2016-08-31 58 views
9

Tôi đang cố gắng tăng khoảng cách giữa tiêu đề chú thích và nhãn trong ggplot2 nhưng chưa có bất kỳ giải pháp nào có thể tìm thấy trên web. Như bạn có thể thấy trong ví dụ tái tạo bên dưới văn bản tiêu đề quá gần với số trên cùng. Tôi muốn tránh các giải pháp clunky (# 6 dưới đây) bằng tay thêm một dòng phanh (\n) vì điều này không cho phép tinh chỉnh kích thước khoảng cách và một dòng hoàn toàn là quá nhiều trong trường hợp của tôi.Tăng khoảng cách giữa tiêu đề chú giải và nhãn trong ggplot2

Tôi cần sử dụng colourbar. Tôi biết rằng vjust thường có giá trị từ 0 đến 1 nhưng tôi đang sử dụng giá trị 2 dưới đây để dễ dàng phát hiện các thay đổi hơn.

library(reshape2) 
library(ggplot2) 

# Generate test data frame 
df=reshape2::melt(outer(1:4, 1:4), varnames = c("X1", "X2")) 

# Declare theme 
mytheme=theme_classic(base_size=15) + 
    theme(axis.title.x=element_blank(),axis.title.y=element_blank(), 
     axis.text.x=element_blank(),axis.text.y=element_blank(), 
     axis.ticks=element_blank()) + 
    theme(legend.position=c(0,1), legend.justification=c(0,1), 
     legend.title=element_text(size="12",face = "bold")) 

# Plot 
p=ggplot(data=df, aes_string(x="X1", y="X2")) + 
    geom_tile(aes(fill=value))+ 
    scale_fill_gradient(low="yellow",high="red",guide="colourbar",name="Titleggplot") + 
    annotate("text",x=Inf,y=Inf,label="(a)" ,hjust=1.5, vjust=1.5, size=6) + 
    mytheme 
p 

#*** Things I tried (building on the defaults above) that do not work 

# 1 - set "vjust" in theme 
mytheme=mytheme+theme(legend.title=element_text(size="12",face = "bold",vjust=2)) 
p=p+mytheme 
p 
# Result: does nothing 

# 2 - set "legend.title.align" in theme 
mytheme=mytheme+theme(legend.title.align=4) 
p=p+mytheme 
p 
# Result: adjusts horizontal position but does not change vertical position 

# 3 - increase margins around title object 
mytheme=mytheme+theme(legend.title=element_text(margin=margin(0,0,20,0),size="12",face="bold")) 
p=p+mytheme 
p 
# Result: does nothing 

# 4 - using "guide" in scale_fill_gradient 
p=ggplot(data=df, aes_string(x="X1", y="X2")) + 
    geom_tile(aes(fill=value))+ 
    scale_fill_gradient(low="yellow",high="red",guide=guide_colorbar(title="Titleggplot",title.vjust=2)) + 
    annotate("text",x=Inf,y=Inf,label="(a)" ,hjust=1.5, vjust=1.5, size=6) + 
    mytheme 
p 
# Result: does nothing 

# 5 - using "guides" as separate element 
p=p+guides(fill=guide_legend(title.vjust=2)) 
# Restult: does nothing 

# 6 - I could manually add a line break (\n) to the title 
p=ggplot(data=df, aes_string(x="X1", y="X2")) + 
    geom_tile(aes(fill=value))+ 
    scale_fill_gradient(low="yellow",high="red",guide="colourbar",name="Titleggplot\n") + 
    annotate("text",x=Inf,y=Inf,label="(a)" ,hjust=1.5, vjust=1.5, size=6) + 
    mytheme 
p 
# Result: increases the space but I can't smoothly adjust the spacing and an entire blank line is in my case too much. 
+2

Tôi nghĩ việc xác định một 'margin' trong 'element_text' có thể làm việc, nhưng nó không. Có thể là một lỗi? – Roland

+0

@Roland gợi ý tốt! Tôi cũng đã thử điều này trước khi không thành công nhưng quên bao gồm mở rộng các lề trong các tùy chọn của tôi ở trên - tôi đã thêm điều này ngay bây giờ. – Raphael

+0

Có ít nhất hai yêu cầu github liên quan đến vấn đề này (xác định lề trong chú giải). Gần đây, tác giả chính của gói cho biết đây không phải là ưu tiên cao. Có lẽ bạn có thể bình luận về một trong số họ ở đó. – lmo

Trả lời

4

Đào vào cấu trúc grob của chú giải, có thể thay thế tiêu đề chú giải ban đầu bằng tựa đề có lề trên và lề dưới. Xem nhận xét trong mã bên dưới.

library(reshape2) 
library(ggplot2) 


# Generate test data frame 
df=reshape2::melt(outer(1:4, 1:4), varnames = c("X1", "X2")) 

# Declare theme 
mytheme=theme_classic(base_size=15) + 
    theme(axis.title.x=element_blank(),axis.title.y=element_blank(), 
     axis.text.x=element_blank(),axis.text.y=element_blank(), 
     axis.ticks=element_blank()) + 
    theme(legend.position=c(0,1), legend.justification=c(0,1), 
     legend.title=element_text(size="12",face = "bold")) 

# Plot 
p=ggplot(data=df, aes_string(x="X1", y="X2")) + 
    geom_tile(aes(fill=value))+ 
    scale_fill_gradient(low="yellow",high="red",guide="colourbar",name="Titleggplot") + 
    annotate("text",x=Inf,y=Inf,label="(a)" ,hjust=1.5, vjust=1.5, size=6) + 
    mytheme 
p 

# Function to set upper and lower margins to legend title 

TitleMargins = function(plot, Tmargin = unit(0, "mm"), Bmargin = unit(0, "mm")) { 
library(gtable) 
library(grid) 

# Get the plot grob 
g = ggplotGrob(plot) 

# Get the legend 
index = which(g$layout$name == "guide-box") 
leg = g$grobs[[index]][[1]][[1]] 

# Get the legend title 
title = leg$grobs[[4]] 

# Set up the heights: for the two margins and the original title 
heights <- unit.c(Tmargin, unit(1, "grobheight", title), Bmargin) 

# Set up a column of three viewports 
vp <- viewport(layout = grid.layout(3, 1, 
        heights = heights), name = "vp1") 

# The middle row, where the title text will appear, is named as 'child_vp'. 
child_vp <- viewport(layout.pos.row = 2, clip = "off", name = "child_vp") 

# Put the title into a gTree containing one grob (the title) and the three viewports 
TitleText <- gTree(children = gList(title), 
        vp = vpTree(vp, vpList(child_vp))) 

# Back to the legend: Set height for row 2 of legend to new height of TitleText 
leg$heights[2] = sum(heights) 

# Add the new TitleText grob to row 2 of legend 
leg <- gtable_add_grob(leg, TitleText, 
       t = 2, l = 2, r = 5, name = "TitleText") 

# Remove the original title 
leg$grobs <- leg$grobs[-4] 
leg$layout <- leg$layout[-4, ] 

# Put the legend back into the plot 
g$grobs[[index]][[1]][[1]] = leg 

class(g) = c("TitleMargins", class(g)) 

g 

} 

# A print method for the plot 
print.TitleMargins <- function(x) { 
    grid.newpage() 
    grid.draw(x) 
} 


# Try it out 
# Set your legend title margins 
Tmargin = unit(0, "mm") 
Bmargin = unit(3, "mm") 

# Apply the function 
TitleMargins(p, Tmargin, Bmargin) 

enter image description here

Các vấn đề liên quan