ggplot2:轴上的花括号?

Posted

技术标签:

【中文标题】ggplot2:轴上的花括号?【英文标题】:ggplot2: Curly braces on an axis? 【发布时间】:2011-08-09 19:27:26 【问题描述】:

在answering a recent visualization 问题中,我确实需要大括号来显示轴上的跨度,但我不知道如何在 ggplot2 中做到这一点。剧情如下:

我真的希望 y 轴标签“双字母名称的第二个字母”有一个从 1 延伸到 10 的大括号(红色和蓝色第二个字母的垂直跨度),而不是刻度线。但我不确定如何做到这一点。 x 轴可以从类似的处理中受益。

链接的 CrossValidated 问题中提供了代码(对于此示例而言,代码过于复杂,因此我不会展示它)。相反,这是一个最小的例子:

library(ggplot2)
x <- c(runif(10),runif(10)+2)
y <- c(runif(10),runif(10)+2)
qplot(x=x,y=y) +
  scale_x_continuous("",breaks=c(.5,2.5),labels=c("Low types","High types") )

在这种情况下,从 (0,1) 开始的大括号代表低类型,从 (2,3) 开始代表高类型将是理想的选择,而不是刻度线。

我宁愿不使用geom_rect,因为:

刻度线将保留 我更喜欢大括号 它将在地块内而不是在地块外

我将如何做到这一点?完美的答案是:

漂亮、光滑、细的花括号 在绘图区域外绘制 通过高级参数指定(最好是传递给scale_x_continuous 中的breaks 选项的范围类型对象)

【问题讨论】:

未经测试,但您的问题似乎很熟悉:***.com/questions/6178763/… @joran:希望有一个 ggplot2 特定的解决方案。我想既然你的(非常酷的)答案是基于网格的而不是基于格的,它应该能够被采用。但我仍然不知道如何关闭刻度线,在绘图区域之外绘制东西等等。 任何解决方案几乎肯定都会涉及到网格。其他代码不是我的(我对网格不太擅长)我只是认为它可能为您或其他人提供了一个很好的起点。 很方便,这是肯定的。我想我的担心(除了前面提到的)是它仍然很笨拙。 ggplot2 非常漂亮,可以将数据与演示文稿分开指定,然后我几乎必须用铅笔画才能使用您提供的精美曲线按照我想要的方式进行绘制。从概念上讲,似乎正确的做法是将跨度对象作为列表的一个元素传递给 scale_x_continuous() 中的中断。 【参考方案1】:

使用绘制大括号的函数的另一种解决方案。

谢谢老师!

curly <- function(N = 100, Tilt = 1, Long = 2, scale = 0.1, xcent = 0.5,
                  ycent = 0.5, theta = 0, col = 1, lwd = 1, grid = FALSE)

# N determines how many points in each curve
# Tilt is the ratio between the axis in the ellipse 
#  defining the curliness of each curve
# Long is the length of the straight line in the curly brackets 
#  in units of the projection of the curly brackets in this dimension
# 2*scale is the absolute size of the projection of the curly brackets 
#  in the y dimension (when theta=0)
# xcent is the location center of the x axis of the curly brackets
# ycent is the location center of the y axis of the curly brackets
# theta is the angle (in radians) of the curly brackets orientation
# col and lwd are passed to points/grid.lines

           ymin <- scale / Tilt
           y2 <- ymin * Long
           i <- seq(0, pi/2, length.out = N)

           x <- c(ymin * Tilt * (sin(i)-1),
                  seq(0,0, length.out = 2),
                  ymin * (Tilt * (1 - sin(rev(i)))),
                  ymin * (Tilt * (1 - sin(i))),
                  seq(0,0, length.out = 2),
                  ymin * Tilt * (sin(rev(i)) - 1))

           y <- c(-cos(i) * ymin,
                  c(0,y2),
                  y2 + (cos(rev(i))) * ymin,
                  y2 + (2 - cos(i)) * ymin,
                  c(y2 + 2 * ymin, 2 * y2 + 2 * ymin),
                  2 * y2 + 2 * ymin + cos(rev(i)) * ymin)

           x <- x + xcent
           y <- y + ycent - ymin - y2

           x1 <- cos(theta) * (x - xcent) - sin(theta) * (y - ycent) + xcent
           y1 <- cos(theta) * (y - ycent) + sin(theta) * (x - xcent) + ycent

           ##For grid library:
           if(grid)
              grid.lines(unit(x1,"npc"), unit(y1,"npc"),gp=gpar(col=col,lwd=lwd))
           

           ##Uncomment for base graphics
           else
              par(xpd=TRUE)
              points(x1,y1,type='l',col=col,lwd=lwd)
              par(xpd=FALSE)
           




library(ggplot2)
x <- c(runif(10),runif(10)+2)
y <- c(runif(10),runif(10)+2)
qplot(x=x,y=y) +
  scale_x_continuous("",breaks=c(.5,2.5),labels=c("Low types","High types") )

curly(N=100,Tilt=0.4,Long=0.3,scale=0.025,xcent=0.2525,
      ycent=par()$usr[3]+0.1,theta=-pi/2,col="red",lwd=2,grid=TRUE)
curly(N=100,Tilt=0.4,Long=0.3,scale=0.025,xcent=0.8,
      ycent=par()$usr[3]+0.1,theta=-pi/2,col="red",lwd=2,grid=TRUE)

【讨论】:

对于像我这样的非数学爱好者 - 如果你在内部使用 theta &lt;- angle*pi/180 将角度转换为弧度,你可以使用 angle 作为函数参数 - 我觉得这更容易。【参考方案2】:

更新:如果您需要使用 ggsave() 保存绘图并在保存的图像中保留括号,请务必查看 this related *** Q&A。


OP 要求括号脱离情节。此解决方案将axis.ticks.lengthaxis.ticks = element_blank() 结合使用,以允许大括号位于绘图区域之外。 这个答案建立在@Pankil 和@user697473 的基础上:我们将使用pBrackets R 包——并包含图片!

library(ggplot2)
library(grid)
library(pBrackets) 
x <- c(runif(10),runif(10)+2)
y <- c(runif(10),runif(10)+2)
the_plot <- qplot(x=x,y=y) +
  scale_x_continuous("",breaks=c(.5,2.5),labels=c("Low types","High types") ) +
  theme(axis.ticks = element_blank(),
        axis.ticks.length = unit(.85, "cm"))


#Run grid.locator a few times to get coordinates for the outer
#most points of the bracket, making sure the 
#bottom_y coordinate is just at the bottom of the gray area.
# to exit grid.locator hit esc; after setting coordinates
# in grid.bracket comment out grid.locator() line
the_plot
grid.locator(unit="native") 
bottom_y <- 284
grid.brackets(220, bottom_y,   80, bottom_y, lwd=2, col="red")
grid.brackets(600, bottom_y,  440, bottom_y, lwd=2, col="red")

关于@Pankil 答案的简要说明:

## Bracket coordinates depend on the size of the plot
## for instance,
## Pankil's suggested bracket coordinates do not work
## with the following sizing:
the_plot
grid.brackets(240, 440, 50, 440, lwd=2, col="red")
grid.brackets(570, 440, 381, 440, lwd=2, col="red")
## 440 seems to be off the graph...

还有几个展示pBrackets的功能:

#note, if you reverse the x1 and x2, the bracket flips:
the_plot
grid.brackets( 80, bottom_y, 220, bottom_y, lwd=2, col="red")
grid.brackets(440, bottom_y, 600, bottom_y, lwd=2, col="red")

## go vertical:
the_plot
grid.brackets(235, 200, 235, 300, lwd=2, col="red")
grid.brackets(445, 125, 445,  25, lwd=2, col="red")

【讨论】:

是的,但是如何保存呢? ggsave 不会添加括号 不错的答案。但它会受益于如何将绘图导出为 PDF 的解释。我已经设法通过 RStudio 的“导出”按钮将其保存到 PNG,但使用 ggsave(...)pdf(...)...dev.off() 等常用解决方案失败了也许grid 包中的某些功能是为此而设计的,例如gridArrange(),但我不能'不要很快找到解决方案。 哦等等:***.com/questions/35633239/… PatrickT -- 我添加了您链接到答案的 SamanthaDS 帖子。谢谢你们。 grid.brackets() 似乎没有在x1 y1 x2 y2 参数告诉他们的地方开始和停止! (它们看起来非常好,只是无法将它们带到应有的位置)【参考方案3】:

这是ggplot 中的 kludgy 解决方案,它构造了一个类似于花括号的线条图。

构造一个函数,将大括号的位置和尺寸作为输入。该函数的作用是指定括号轮廓图的坐标,并使用一些数学缩放将其调整到所需的大小和位置。您可以使用此原则并修改坐标以提供任何所需的形状。原则上您可以使用相同的概念并添加曲线、椭圆等。

bracket <- function(x, width, y, height)
  data.frame(
      x=(c(0,1,4,5,6,9,10)/10-0.5)*(width) + x,
      y=c(0,1,1,2,1,1,0)/2*(height) + y
  )

将其传递给ggplot,特别是geom_line

qplot(x=x,y=y) +
    scale_x_continuous("",breaks=c(.5,2.5), labels=c("Low types","High types")) +
    geom_line(data=bracket(0.5,1,0,-0.2)) +
    geom_line(data=bracket(2.5,2,0,-0.2))

【讨论】:

不错。您可以结合此处的答案将大括号移近轴:***.com/questions/7001710/…【参考方案4】:

正如@user697473 建议的pBrackets 是优雅的解决方案。

使用默认绘图命令效果最好,但要使其与 GGplot2 一起使用,请使用 pBracket::grid.brackets。我包含代码以便于试用。

您的代码开始..

library(ggplot2)
x <- c(runif(10),runif(10)+2)
y <- c(runif(10),runif(10)+2)
qplot(x=x,y=y) +
  scale_x_continuous("",breaks=c(.5,2.5),labels=c("Low types","High types") ) +
  theme(axis.ticks = element_blank())

最后一行删除了您不想要的刻度。 现在pBrackets

library(pBrackets)  # this will also load grid package
grid.locator(unit="native") 

现在使用您的光标确定图表上括号开始和结束的点。您将以“本机”单位获得相应的坐标。现在在下面的命令中输入它们

grid.brackets(240, 440, 50, 440, lwd=2, col="red")
grid.brackets(570, 440, 381, 440, lwd=2, col="red")

您可以在图表的任意位置添加括号,甚至可以使用grid.text 添加文本。

希望这会有所帮助!谢谢pBrackets

潘基尔!

【讨论】:

【参考方案5】:

新的pbrackets 包可能会有所帮助:http://cran.r-project.org/web/packages/pBrackets/index.html

【讨论】:

不错!它导入grid,所以应该与ggplot2一起使用。 一个不错的项目,但不是超级好用。看后续:***.com/questions/35633239/…【参考方案6】:

#== 编辑:ggbrace 替换了 curlyBraces 包

这个答案真的很晚,但是对于绘图区域内的大括号,我做了一个小包ggbrace,它可以让你有你指定的坐标的花括号(易于使用):

基本上:

devtools::install_github("NicolasH2/ggbrace")
library(ggbrace)
library(ggplot2)

您可以自定义 x 和 y 坐标以及括号指向的位置。在这种特定情况下:

x <- c(runif(10),runif(10)+2)
y <- c(runif(10),runif(10)+2)

qplot(x=x,y=y) +
  scale_x_continuous("",breaks=c(.5,2.5),labels=c("Low types","High types") ) + 
  geom_brace(aes(x=c(0,1), y=c(0,-.3)), inherit.data=F, rotate=180) + 
  geom_brace(aes(x=c(2,3), y=c(0,-.3)), inherit.data=F, rotate=180)

编辑:如果你想要绘图区域之外的大括号,你可以设置一些 ggplot 参数。在 ggbrace github 页面上有更详细的描述。

qplot(x=x,y=y) +
  geom_brace(aes(x=c(0,1), y=c(-.4,-.7), label = "Low types"), inherit.data=F, rotate=180, labelsize=5) + 
  geom_brace(aes(x=c(2,3), y=c(-.4,-.7), label = "High types"), inherit.data=F, rotate=180, labelsize=5) +
  coord_cartesian(y=range(y), clip = "off") +
  theme(plot.margin = unit(c(0.05, 0.05, 0.2, 0.05), units="npc"))

【讨论】:

以上是关于ggplot2:轴上的花括号?的主要内容,如果未能解决你的问题,请参考以下文章

Java中的花括号本身是啥意思?

函数的 JavaScript 参数中的花括号

Scala方法调用中的花括号[重复]

关于if语句后面的花括号

获取所有嵌套的花括号

XAML 中的花括号实际上是啥意思?