如何将图例高度设置为与绘图区域的高度相同? [英] How to set legend height to be the same as the height of the plot area?
问题描述
我希望热图图例具有与图的绘图区相同的高度热图,即与y轴相同的长度。我知道我可以使用主题(legend.key.height = unit(...))
来更改图例的高度和大小,但这需要很多试用并且在找到适当的设置之前发生错误。
有没有一种方法可以指定图例的高度,使其与热图的绘图区域的高度完全相同,并在绘图时保留该比率我有一个可重复的代码示例:
#创建一些测试数据
pp < - 函数(n,r = 4){
x < - seq(1:100)
df< - expand.grid(x = x ,y = 1:10)
df $ z < - df $ x * df $ y
df
}
testD< - pp(20)
#define组
colbreaks< - seq(min(testD [,3]),max(testD [,3] + 1),length = 5)
library(Hmisc)
testD $ group< - cut2(testD [,3],cuts = c(colbreaks))
detach(package:Hmisc,unload = TRUE)
#为顶部绘图创建数据
testD_agg< - aggregate(。〜x,data = testD [,c(1,3)],FUN = sum)
#底图(热图)
library ggplot2)
library(gtable)
p < - ggplot(testD,aes(x = x,y = y))+
geom_tile(aes(fill = group)) +
scale_f ill_manual(values = c(red,orange,yellow,lightgreen))+
coord_cartesian(xlim = c(0,100),ylim = c(0.5,10.5))+
theme_bw()+
主题(legend.position =right,
legend.key = element_blank(),
legend.text = element_text(color =黑色,size = 12),
legend.title = element_blank(),
axis.text.x = element_text(size = 12,angle = 45,vjust = +0.5),
axis.text.y = element_text(size = 12),
axis.title = element_text(size = 14),
panel.grid.major = element_blank(),
panel.grid。 minor = element_blank(),
plot.margin =单位(c(0,0,0,0),line))
#Top plot(line)
p2 < - ggplot(testD_agg,aes(x = x,y = z))+
geom_line()+
xlab(NULL)+
coord_cartesian(xlim = c(0,100 ),ylim = c(0,max(testD_agg $ z)))+
theme_bw()+
theme(legend.position =none,
legend.key = element_blank(),
legend.text = element_text(color =black,size = 12),
legend.title = element_text(size = 12,face =plain),
axis.text.x = element_blank ),
axis.text.y = element_text(size = 12),
axis.title = element_text(size = 14),
axis.ticks.x = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.margin =单位(c(0.5,0.5,0,0),line ))
#创建gtables
gp< - ggplotGrob(p)
gp2< - ggplotGrob(p2)
#宽度等于底图的图例的右顶部
legend.width< - gp $ widths [7:8]#获得pff2中图例的宽度
gp2< - gtable_add_cols (gp2,legend.width,4)#使用legend.with添加一个柱子到pff
#组合地块
cg < - rbind(gp2,gp,size =last)
#设置地块的比例
面板< - cg $ layout $ t [grep(panel,cg $ layout $ na (c(2,3),null)
#删除图之间的白色间距
cg < - gtable_add_rows(cg ,unit(0,npc),pos = nrow(gp))
pdf(test.pdf,width = 8,height = 7)
print(grid.draw (cg))
dev.off()
#以下并没有帮助解决我的问题,但我认为我已经接近
old.height< - cg $ grobs [ [16]] $ heights [2]
#传说的高度似乎以mm给出,改为npc?
gp $ grobs [[8]] $ grobs [[1]] $ heights< -c(rep(unit(0,npc),3),rep(unit(1/4,npc ),4),rep(单位(0,mm),1))
#this允许调整高度,但不是我需要的精确控制。
我的实际数据有更多类别,但要点相同。
此处是使用上述代码生成的图像,并用我想要做什么。
预先感谢!
Maarten
似乎有两组高度需要调整:图例按键的高度,以及传说的整体高度。从你的 cg
grob拾起,我提取图例,调整高度,然后将图例grob插回到布局中。
leg = gtable_filter(cg,guide-box)
库(网格)
#图例
leg [[1]] [[1]] [[1]] [[1]] $ heights = unit.c(rep(unit(0,mm),3),$ b $ (单位(1/4,npc),4),
单位(0,mm))
#图例
leg [[1]] [$ 1] $ heights [[3]] = sum(rep(单位(0,mm),3),
rep(单位(1/4,npc),4),
unit(0,mm))
#grid.draw(leg)#检查高度是否正确
cg.new = gtable_add_grob(cg,leg ,t = 17,l = 8)
grid.newpage()
grid.draw(cg.new)
I have arranged two plots: a line chart on top and a heatmap below.
I want the heatmap legend to have the same height as the plot area of the heatmap, i.e. the same length as the y-axis. I know that I can change the height and size of the legend using theme(legend.key.height = unit(...))
, but this would take many trial and errors before I find an adequate setting.
Is there a way to specify the height of the legend so that it is exactly the same height of the plot area of the heatmap and would retain that ratio when plotting to a pdf?
A reproducible example with code I have tried:
#Create some test data
pp <- function (n, r = 4) {
x <- seq(1:100)
df <- expand.grid(x = x, y = 1:10)
df$z <- df$x*df$y
df
}
testD <- pp(20)
#Define groups
colbreaks <- seq(min(testD[ , 3]), max(testD[ , 3] + 1), length = 5)
library(Hmisc)
testD$group <- cut2(testD[ , 3], cuts = c(colbreaks))
detach(package:Hmisc, unload = TRUE)
#Create data for the top plot
testD_agg <- aggregate(.~ x, data=testD[ , c(1, 3)], FUN = sum)
#Bottom plot (heatmap)
library(ggplot2)
library(gtable)
p <- ggplot(testD, aes(x = x, y = y)) +
geom_tile(aes(fill = group)) +
scale_fill_manual(values = c("red", "orange", "yellow", "lightgreen")) +
coord_cartesian(xlim = c(0, 100), ylim = c(0.5, 10.5)) +
theme_bw() +
theme(legend.position = "right",
legend.key = element_blank(),
legend.text = element_text(colour = "black", size = 12),
legend.title = element_blank(),
axis.text.x = element_text(size = 12, angle = 45, vjust = +0.5),
axis.text.y = element_text(size = 12),
axis.title = element_text(size = 14),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.margin = unit(c(0, 0, 0, 0), "line"))
#Top plot (line)
p2 <- ggplot(testD_agg, aes(x = x, y = z)) +
geom_line() +
xlab(NULL) +
coord_cartesian(xlim = c(0, 100), ylim = c(0, max(testD_agg$z))) +
theme_bw() +
theme(legend.position = "none",
legend.key = element_blank(),
legend.text = element_text(colour = "black", size = 12),
legend.title = element_text(size = 12, face = "plain"),
axis.text.x = element_blank(),
axis.text.y = element_text(size = 12),
axis.title = element_text(size = 14),
axis.ticks.x = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.margin = unit(c(0.5, 0.5, 0, 0), "line"))
#Create gtables
gp <- ggplotGrob(p)
gp2 <- ggplotGrob(p2)
#Add space to the right of the top plot with width equal to the legend of the bottomplot
legend.width <- gp$widths[7:8] #obtain the width of the legend in pff2
gp2 <- gtable_add_cols(gp2, legend.width, 4) #add a colum to pff with with legend.with
#combine the plots
cg <- rbind(gp2, gp, size = "last")
#set the ratio of the plots
panels <- cg$layout$t[grep("panel", cg$layout$name)]
cg$heights[panels] <- unit(c(2,3), "null")
#remove white spacing between plots
cg <- gtable_add_rows(cg, unit(0, "npc"), pos = nrow(gp))
pdf("test.pdf", width = 8, height = 7)
print(grid.draw(cg))
dev.off()
#The following did not help solve my problem but I think I got close
old.height <- cg$grobs[[16]]$heights[2]
#It seems the height of the legend is given in "mm", change to "npc"?
gp$grobs[[8]]$grobs[[1]]$heights <- c(rep(unit(0, "npc"), 3), rep(unit(1/4, "npc"), 4), rep(unit(0, "mm"),1))
#this does allow for adjustment of the heights but not the exact control I need.
My actual data has some more categories, but the gist is the same. Here is an image produced with the code above and annotated with what I would like to do.
Thanks in advance! Maarten
It seems there are two sets of heights that need adjustment: the heights of the legend keys, and the overall height of the legend. Picking up from your cg
grob, I extract the legend, make the adjustments to the heights, then insert the legend grob back into the layout.
leg = gtable_filter(cg, "guide-box")
library(grid)
# Legend keys
leg[[1]][[1]][[1]][[1]]$heights = unit.c(rep(unit(0, "mm"), 3),
rep(unit(1/4, "npc"), 4),
unit(0, "mm"))
# Legend
leg[[1]][[1]]$heights[[3]] = sum(rep(unit(0, "mm"), 3),
rep(unit(1/4, "npc"), 4),
unit(0, "mm"))
# grid.draw(leg) # Check that heights are correct
cg.new = gtable_add_grob(cg, leg, t = 17, l = 8)
grid.newpage()
grid.draw(cg.new)
这篇关于如何将图例高度设置为与绘图区域的高度相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!