如何在ggplot2的绘图区域外画线? [英] How to draw lines outside of plot area in ggplot2?

查看:60
本文介绍了如何在ggplot2的绘图区域外画线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用 ggplot2 创建了这个图:

外线需要对应 Y 刻度,(即 Text1 的线的 Y 位置应为 100 和 85).我可以通过在图形右侧绘制一个与条形图相同比例的空白图,然后使用 annotate 函数绘制线条来完成此操作的唯一方法.另一种方法是使用 grid.lines 简单地手动"绘制线条,但是 grid.lines 的坐标将不对应于绘图的 Y 比例.

是否可以使用不同的方法以某种方式绘制这些线?我认为必须使用 grid.lines 来完成.如何将条形图的 Y 坐标传递给 grid.lines?

以下是用于创建此图形的最少代码:

库(ggplot2)测试=数据.框架(组=c(rep(1,6), rep(2,6)),子组=c(1,1,1,2,2,2,1,1,1,2,2,2),类别=c(代表(1:3,4)),计数=c( 10,80,10,5,90,5, 10,80,10,5,90,5 ))qplot(子组,数数,数据=测试,几何=酒吧",统计=身份",填写=类别,facets = .~ 组,宽度=0.9)+opts(legend.position="none",plot.margin = unit(c(0,9,2,0), "lines"))

如何在条形右侧绘制线条?

我最近问了一个关于在 ggplot2 绘图区域外绘制文本的问题,解决方案是使用 gt$layoutgrid.draw.

在 ggplot2 生成的绘图下方显示文本

这里可以使用类似的方法吗?我的理解是 annotation_custom 仅适用于文本,不适用于其他图形元素.谢谢

解决方案

更新

最初的解决方案使用annotation_custom,但是annotation_custom 的一个问题是它在所有面板中绘制了注释.但是,通过简单的修改,annotation_custom 可以只在一个面板中绘制(取自 Baptiste 的回答 此处)

annotation_custom2 <-函数(grob,xmin = -Inf,xmax = Inf,ymin = -Inf,ymax = Inf,数据){层(数据 = 数据,统计 = StatIdentity,位置 = PositionIdentity,geom = ggplot2:::GeomCustomAnn,继承.aes = TRUE, params = list(grob = grob,xmin = xmin, xmax = xmax,ymin = ymin, ymax = ymax))}图书馆(ggplot2)图书馆(网格)#一些数据测试 = 数据.frame(组=c(rep(1,6), rep(2,6)),子组=c(1,1,1,2,2,2,1,1,1,2,2,2),类别=c(代表(1:3,4)),计数=c( 10,80,10,5,90,5, 10,80,10,5,90,5 ))# 基础图p <- ggplot(test) +geom_bar(aes(subgroup, count, fill = category), stat = "identity") +facet_grid(.~组) +主题(legend.position =无",plot.margin = unit(c(1,5,1,1), "lines"))# 创建文本 GrobsText1 = textGrob("文本 1")Text2 = textGrob("文本 2")Text4 = textGrob("文本 4")## 添加注释# 哪个面板要附加注释数据 = 数据.frame(组 = 2)# 文本1p1 = 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)# 文字 2p1 = 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)# 文字 4p1 = 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)# 覆盖裁剪的代码gt <- ggplotGrob(p1)gt$layout[grepl("panel", gt$layout$name), ]$clip <- "off"# 绘制曲线grid.newpage()grid.draw(gt)

原始解决方案

我认为几乎所有使用 grid() 创建的 Grob 都可以在 annotation_custom() 中使用.可能有更简洁的方法来做到这一点,但这里有一种使用 gridannotation_custom 和 @baptiste 的代码 从这里覆盖剪裁(如之前的帖子).

库(ggplot2)图书馆(网格)测试=数据.框架(组=c(rep(1,6), rep(2,6)),子组=c(1,1,1,2,2,2,1,1,1,2,2,2),类别=c(代表(1:3,4)),计数=c( 10,80,10,5,90,5, 10,80,10,5,90,5 ))## 更新 qplot() 命令p <- qplot(子组,计数,数据 = 测试,geom = "bar",stat = "identity",填充 = 类别,面 = .~ 组,宽度 = 0.9)+主题(legend.position="none", plot.margin = unit(c(0,9,2,0), "lines"))# 创建文本 GrobsText1 = textGrob("文本 1")Text2 = textGrob("文本 2")Text4 = textGrob("文本 4")# 绘制曲线# 文本1p1 = 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)# 文字 2p1 = 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)# 文字 4p1 = 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# 覆盖裁剪的代码gt <- ggplot_gtable(ggplot_build(p1))gt$layout$clip[gt$layout$name==面板"] <-关闭"grid.draw(gt)

I created this plot with ggplot2:

The outside lines need to correspond to the Y scale, (i.e the Y position of the lines for Text1 should be 100 and 85). The only way I can do it by drawing a blank plot to the right of the figure with the same scale as the barchart and then using annotate function to draw the lines. Another approach is to simply "manually" draw the lines with grid.lines, however the coordinates of grid.lines will not correspond to the Y scale of the plot.

Is it possible to somehow draw these lines using a different approach? I assume it would have to be done with grid.lines. How could I pass Y coordindates of the barchart to grid.lines?

Below is the minimal code used to create this figure:

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"))

How can I draw the lines to the right of the bars?

I recently asked a question about drawing text outside of plot area in ggplot2 and the solution was to use gt$layout and grid.draw.

Displaying text below the plot generated by ggplot2

Could the similar approach be used here? It is my understanding that annotation_custom is for text only and won't work with other graphical elements. Thanks

解决方案

Update

The original solution used annotation_custom, but a problem with annotation_custom is that it draws the annotation in all panels. However, with a simple modification, annotation_custom can be made to draw in one panel only (taken from Baptiste's answer here)

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)

Original Solution

I think almost any Grob created using grid() can be used in annotation_custom(). There might be neater ways to do this, but here's a way using grid, annotation_custom and @baptiste's code from here to override the clipping (as in the earlier post).

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)

这篇关于如何在ggplot2的绘图区域外画线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆