[英]How to draw lines outside of plot area in ggplot2?
我用ggplot2创建了这个图:
外部线需要对应于Y比例尺(即Text1的线的Y位置应为100和85)。 我可以做到的唯一方法是在图的右侧绘制一个与条形图相同比例的空白图,然后使用注释功能绘制线条。 另一种方法是简单的“手动”绘制线条grid.lines
,但是坐标grid.lines
将不符合情节的Y规模。
是否可以使用其他方法以某种方式画出这些线? 我认为必须使用grid.lines
完成。 如何将条形图的Y坐标传递给grid.lines
?
以下是用于创建该图形的最少代码:
library (ggplot2)
test= data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5 )
)
qplot(subgroup,
count,
data=test,
geom="bar",
stat="identity",
fill =category,
facets = .~ group, width=0.9)+
opts(legend.position="none",
plot.margin = unit(c(0,9,2,0), "lines"))
如何在条形的右边画线?
我最近问了一个有关在ggplot2中在绘图区域之外绘制文本的问题,解决方案是使用gt$layout
和grid.draw
。
可以在这里使用类似的方法吗? 据我了解,annotation_custom仅用于文本,不能与其他图形元素一起使用。 谢谢
更新资料
最初的解决方案中使用annotation_custom
,但有一个问题annotation_custom
是,它在吸引所有面板的注释。 然而,简单的修改, annotation_custom
可制成只有一个面板绘制(从巴蒂斯特的答案采取这里 )
annotation_custom2 <-
function (grob, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, data)
{
layer(data = data, stat = StatIdentity, position = PositionIdentity,
geom = ggplot2:::GeomCustomAnn,
inherit.aes = TRUE, params = list(grob = grob,
xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax))
}
library(ggplot2)
library(grid)
#Some data
test = data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5 )
)
# base plot
p <- ggplot(test) +
geom_bar(aes(subgroup, count, fill = category), stat = "identity") +
facet_grid(. ~ group) +
theme(legend.position = "none",
plot.margin = unit(c(1,5,1,1), "lines"))
# Create the text Grobs
Text1 = textGrob("Text 1")
Text2 = textGrob("Text 2")
Text4 = textGrob("Text 4")
## Add the annotations
# Which panel to attach the annotations
data = data.frame(group=2)
# Text 1
p1 = p + annotation_custom2(Text1, xmin = 3., xmax = 3., ymin = 85, ymax = 100, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 100, ymax = 100, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 85, ymax = 85, data = data) +
annotation_custom2(linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 85, ymax = 100, data = data)
# Text 2
p1 = p1 + annotation_custom2(Text2, xmin = 3, xmax = 3, ymin = 20, ymax = 80, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 80, ymax = 80, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 20, ymax = 20, data = data) +
annotation_custom2(linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 20, ymax = 80, data = data)
# Text 4
p1 = p1 + annotation_custom2(Text4, xmin = 3, xmax = 3, ymin = 0, ymax = 15, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 15, ymax = 15, data = data) +
annotation_custom2(linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 0, ymax = 0, data = data) +
annotation_custom2(linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 0, ymax = 15, data = data)
# Code to override clipping
gt <- ggplotGrob(p1)
gt$layout[grepl("panel", gt$layout$name), ]$clip <- "off"
# Draw the plot
grid.newpage()
grid.draw(gt)
原始解决方案
我认为几乎所有使用grid()
创建的Grob都可以在annotation_custom()
。 可能有更巧妙的方法来执行此操作,但是这是从此处使用grid
, annotation_custom
和@baptiste的代码来覆盖剪切的一种方法(如先前的文章中所述)。
library (ggplot2)
library(grid)
test= data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5 )
)
## EDIT: Updated qplot() command
p <- qplot(subgroup, count,
data = test, geom = "bar", stat = "identity",
fill = category,
facets = .~ group, width = 0.9)+
theme(legend.position="none", plot.margin = unit(c(0,9,2,0), "lines"))
# Create the text Grobs
Text1 = textGrob("Text 1")
Text2 = textGrob("Text 2")
Text4 = textGrob("Text 4")
# Draw the plot
# Text 1
p1 = p + annotation_custom(grob = Text1, xmin = 3., xmax = 3., ymin = 85, ymax = 100) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 100, ymax = 100) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 85, ymax = 85) +
annotation_custom(grob = linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 85, ymax = 100)
# Text 2
p1 = p1 + annotation_custom(grob = Text2, xmin = 3, xmax = 3, ymin = 20, ymax = 80) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 80, ymax = 80) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 20, ymax = 20) +
annotation_custom(grob = linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 20, ymax = 80)
# Text 4
p1 = p1 + annotation_custom(grob = Text4, xmin = 3, xmax = 3, ymin = 0, ymax = 15) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 15, ymax = 15) +
annotation_custom(grob = linesGrob(), xmin = 2.6, xmax = 2.75, ymin = 0, ymax = 0) +
annotation_custom(grob = linesGrob(), xmin = 2.75, xmax = 2.75, ymin = 0, ymax = 15)
p1
# Code to override clipping
gt <- ggplot_gtable(ggplot_build(p1))
gt$layout$clip[gt$layout$name=="panel"] <- "off"
grid.draw(gt)
更新 opts
已弃用; 改用theme
。
这是另一个解决方案。 解决了两个面板中的annotation_custom()
绘图问题。 它绘制了两个图形:第一个是您的条形图;第二个是您的条形图。 第二个仅包含注释。 然后使用gridExtra
包中的grid.arrange()
将两者放在一起。 但是,您的折线问题仍然存在。
在两个图中,仍然存在使y轴比例相同的问题。 但是只要小心,就可以做到。 在包含注释的图形中,请注意如何删除不会对y轴比例产生影响的元素(通过theme_blank()
,而是将其隐藏(使用colour = NA
)。
library(ggplot2)
library(gridExtra)
library(grid)
test= data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5))
# The bar plot
p1 <- ggplot(test, aes(subgroup, count, fill = category)) +
geom_bar(stat = "identity") +
facet_grid(.~ group) +
theme(legend.position = "none",
plot.margin = unit(c(1,0,2,0), "lines"))
p1 <- p1 + ylim(0, 100)
# The empty plot to contain the annotations
p2 = ggplot(data.frame(x = c(1,2), y = c(0,100), z = c(1,1)), aes(x,y)) + theme_bw() + facet_wrap(~ z) +
theme(axis.title.y = element_blank(),
axis.title.x = element_text(colour = NA),
axis.text.y = element_blank(),
axis.text.x = element_text(colour = NA),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.ticks = element_line(colour = NA),
panel.border = element_rect(colour = NA),
strip.background = element_rect(colour = NA, fill = NA),
strip.text.x = element_text(colour = NA),
plot.margin = unit(c(1,0,2,0), "lines"))
# The annotations
Text1 = textGrob("Text 1")
Text2 = textGrob("Text 2")
Text4 = textGrob("Text 4")
p2 = p2 + annotation_custom(grob = Text1, xmin = 1.4, xmax = 1.4, ymin = 85, ymax = 100) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 100, ymax = 100) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 85, ymax = 85) +
annotation_custom(grob = linesGrob(), xmin = 1.1, xmax = 1.1, ymin = 85, ymax = 100)
p2 = p2 + annotation_custom(grob = Text2, xmin = 1.4, xmax = 1.4, ymin = 20, ymax = 80) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 80, ymax = 80) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 20, ymax = 20) +
annotation_custom(grob = linesGrob(), xmin = 1.1, xmax = 1.1, ymin = 20, ymax = 80)
p2 = p2 + annotation_custom(grob = Text4, xmin = 1.4, xmax = 1.4, ymin = 0, ymax = 15) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 15, ymax = 15) +
annotation_custom(grob = linesGrob(), xmin = 1, xmax = 1.1, ymin = 0, ymax = 0) +
annotation_custom(grob = linesGrob(), xmin = 1.1, xmax = 1.1, ymin = 0, ymax = 15)
# Putting the two plots together
plot = arrangeGrob(p1, p2, ncol = 2, widths = unit(c(10, 2), c("null", "null")))
grid.draw(plot)
我使用以下链接中的代码添加了行/文本: 在ggplot2中使用grconvertX / grconvertY 。 这种方法使用grid.text和grid.lines而不是grobs。 我不确定哪种方法更好。
我认为可以将grid.lines合并为grid.polyline语句,也可以通过循环来完成。 可以将x和y位置设置为一个变量,而不是在每一行中进行硬编码。
唯一可能的麻烦是将比例传递到视口。 但是,只要在GGPLOT和视口中使用相同的比例尺,此代码就应该起作用。 请注意,视口将图的整个高度用作0到100。
library (ggplot2)
library(grid)
library(gridBase)
test= data.frame(
group=c(rep(1,6), rep(2,6)),
subgroup=c( 1,1,1,2,2,2,1,1,1,2,2,2),
category=c( rep(1:3, 4)),
count=c( 10,80,10,5,90,5, 10,80,10,5,90,5 )
)
qplot(subgroup, count,
data=test, geom="bar", stat="identity",
fill =category,
facets = .~ group, width=0.9)+
opts(legend.position="none", plot.margin = unit(c(0,9,2,0), "lines"))
current.vpTree()
downViewport('panel-4-6')
pushViewport(dataViewport( yscale=c(0,100), clip='off',xscale=c(0,1)))
grid.text(x=1.21, y = 90, default.units='native' ,label="Text 1")
grid.text(x=1.21, y = 55, default.units='native' ,label="Text 2")
grid.text(x=1.21, y = 10, default.units='native' ,label="Text 3")
grid.lines(x=c(1.02,1.12), y = c(95,95), default.units='native' )
grid.lines(x=c(1.02,1.12), y = c(85, 85), default.units='native' )
grid.lines(x=c(1.12,1.12), y = c(85, 95), default.units='native' )
grid.lines(x=c(1.02,1.12), y = c(80, 80), default.units='native' )
grid.lines(x=c(1.02,1.12), y = c(20, 20), default.units='native' )
grid.lines(x=c(1.12,1.12), y = c(80, 20), default.units='native' )
grid.lines(x=c(1.02,1.12), y = c(5, 5), default.units='native' )
grid.lines(x=c(1.02,1.12), y = c(15, 15), default.units='native' )
grid.lines(x=c(1.12,1.12), y = c(5, 15), default.units='native' )
对于任何格式问题,我们深表歉意-我只是粘贴了代码,然后使用代码按钮对其进行了缩进。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.