在 ggplot 中为多边形创建一个孔以用作遮罩。

huangapple go评论74阅读模式
英文:

R make a hole in a polygon for a ggplot mask

问题

我正在为一个 ggplot 制作一个遮罩。如何在不使用 GIS 过程的情况下删除在 ggplot 上绘制的圆内部的区域?我有一个用于在图表上创建边界框和圆的 data.frame,如下所示:

library(ggplot2)
bndBox <- data.frame(x=c(-Inf,Inf,Inf,-Inf),
                     y=c(Inf,Inf,-Inf,-Inf),
                     id="bnd")

hole <- data.frame(
  x = cos(seq(0, 2*pi, length.out = 360)),
  y = sin(seq(0, 2*pi, length.out = 360)),
  id="circle"
)

porthole <- rbind(bndBox,hole)

ggplot() + 
  # 我希望能够看到这个点
  geom_point(aes(x = 0,y = 0)) +
  # 但不希望看到这个点
  geom_point(aes(x = -1,y = 0)) +
  geom_polygon(data=porthole, 
               aes(x = x, y = y, fill = id),
               inherit.aes = FALSE)

在 ggplot 中为多边形创建一个孔以用作遮罩。

英文:

i'm making a mask for a ggplot. How can I delete the area inside a circle drawn over a ggplot without using GIS procedures? I have a data.frame used to make a bounding box over a plot and a circle, as follows:

library(ggplot2)
bndBox &lt;- data.frame(x=c(-Inf,Inf,Inf,-Inf),
                     y=c(Inf,Inf,-Inf,-Inf),
                     id=&quot;bnd&quot;)

hole &lt;- data.frame(
  x = cos(seq(0, 2*pi, length.out = 360)),
  y = sin(seq(0, 2*pi, length.out = 360)),
  id=&quot;circle&quot;
)

porthole &lt;- rbind(bndBox,hole)

ggplot() + 
  # I want to be able to see this point
  geom_point(aes(x = 0,y = 0)) +
  # But not this point
  geom_point(aes(x = -1,y = 0)) +
  geom_polygon(data=porthole, 
               aes(x = x, y = y, fill = id),
               inherit.aes = FALSE)

在 ggplot 中为多边形创建一个孔以用作遮罩。

答案1

得分: 1

已更新的答案考虑到,顺时针进行的封闭多边形形成一个孔。


library(ggplot2)

bndBox &lt;- data.frame(x=c(-Inf,-Inf,Inf,Inf, -Inf),
                     y=c(-Inf,Inf,Inf,-Inf, -Inf),
                     id=&quot;bnd&quot;)

bndBox &lt;- data.frame(x=c(-1,1,1,-1, -1),
                     y=c(-1,-1,1,1, -1),
                     id=&quot;bnd&quot;)

hole &lt;- data.frame(
  x = cos(seq(0, 2*pi, length.out = 360)) * 0.95,
  y = sin(seq(0, 2*pi, length.out = 360)) * 0.95,
  id=&quot;circle&quot;
)


porthole &lt;- rbind(bndBox,hole)

ggplot() + 
  geom_polygon(data=porthole, 
               aes(x = x, y = y), fill = &quot;red&quot;)+
  geom_point(aes(x = 0, y = 0)) +
  coord_fixed() +
  theme_void()

在 ggplot 中为多边形创建一个孔以用作遮罩。<!-- -->

<sup>Created on 2023-06-15 with reprex v2.0.2</sup>

英文:

Updated answer to take into account that a closed polygon progressing clockwise forms a hole.


library(ggplot2)

bndBox &lt;- data.frame(x=c(-Inf,-Inf,Inf,Inf, -Inf),
                     y=c(-Inf,Inf,Inf,-Inf, -Inf),
                     id=&quot;bnd&quot;)

bndBox &lt;- data.frame(x=c(-1,1,1,-1, -1),
                     y=c(-1,-1,1,1, -1),
                     id=&quot;bnd&quot;)

hole &lt;- data.frame(
  x = cos(seq(0, 2*pi, length.out = 360)) * 0.95,
  y = sin(seq(0, 2*pi, length.out = 360)) * 0.95,
  id=&quot;circle&quot;
)


porthole &lt;- rbind(bndBox,hole)

ggplot() + 
  geom_polygon(data=porthole, 
               aes(x = x, y = y), fill = &quot;red&quot;)+
  geom_point(aes(x = 0, y = 0)) +
  coord_fixed() +
  theme_void()

在 ggplot 中为多边形创建一个孔以用作遮罩。<!-- -->

<sup>Created on 2023-06-15 with reprex v2.0.2</sup>

答案2

得分: 0

我可以使用 sf 做我想做的事情,但希望不要走这条路,因为我发现代码难以理解,感觉像是 geom_polygon() 应该能够处理它。以下是一个繁琐的解决方案:

library(ggplot2)
library(sf)

bndBox <- data.frame(x=c(-1,1,1,-1),
                     y=c(1,1,-1,-1),
                     id="bnd")
hole <- data.frame(
  x = cos(seq(0, 2*pi, length.out = 360)),
  y = sin(seq(0, 2*pi, length.out = 360)),
  id="circle"
)

portholeSF <- st_sfc(
  st_polygon(
    list(
      hole = cbind(
        c(hole$x,hole$x[1]), 
        c(hole$y,hole$y[1])
      ),
      bnd = cbind(
        c(bndBox$x,bndBox$x[1]), 
        c(bndBox$y,bndBox$y[1])
      )
    )
  )
)

ggplot() + 
  # 我想看到这个点
  geom_point(aes(x = 0,y = 0)) +
  # 但不想看到这个点
  geom_point(aes(x = -0.75,y = 0.75)) +
  geom_sf(data = portholeSF)

请注意,我只翻译了代码的注释和文字内容,代码本身没有翻译。

英文:

I can do what I want with sf but was hoping not to go down this road as I find the code hard to follow and feel like geom_polygon() should be able to handle it. Here is a cumbersome solution:

library(ggplot2)
library(sf)

bndBox &lt;- data.frame(x=c(-1,1,1,-1),
                     y=c(1,1,-1,-1),
                     id=&quot;bnd&quot;)
hole &lt;- data.frame(
  x = cos(seq(0, 2*pi, length.out = 360)),
  y = sin(seq(0, 2*pi, length.out = 360)),
  id=&quot;circle&quot;
)


portholeSF &lt;- st_sfc(
  st_polygon(
    list(
      hole = cbind(
        c(hole$x,hole$x[1]), 
        c(hole$y,hole$y[1])
      ),
      bnd = cbind(
        c(bndBox$x,bndBox$x[1]), 
        c(bndBox$y,bndBox$y[1])
      )
    )
  )
)

ggplot() + 
  # I want to see this point
  geom_point(aes(x = 0,y = 0)) +
  # But not this point
  geom_point(aes(x = -0.75,y = 0.75)) +
  geom_sf(data = portholeSF)

huangapple
  • 本文由 发表于 2023年6月16日 05:42:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76485708.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定