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

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

R make a hole in a polygon for a ggplot mask

问题

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

  1. library(ggplot2)
  2. bndBox <- data.frame(x=c(-Inf,Inf,Inf,-Inf),
  3. y=c(Inf,Inf,-Inf,-Inf),
  4. id="bnd")
  5. hole <- data.frame(
  6. x = cos(seq(0, 2*pi, length.out = 360)),
  7. y = sin(seq(0, 2*pi, length.out = 360)),
  8. id="circle"
  9. )
  10. porthole <- rbind(bndBox,hole)
  11. ggplot() +
  12. # 我希望能够看到这个点
  13. geom_point(aes(x = 0,y = 0)) +
  14. # 但不希望看到这个点
  15. geom_point(aes(x = -1,y = 0)) +
  16. geom_polygon(data=porthole,
  17. aes(x = x, y = y, fill = id),
  18. 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:

  1. library(ggplot2)
  2. bndBox &lt;- data.frame(x=c(-Inf,Inf,Inf,-Inf),
  3. y=c(Inf,Inf,-Inf,-Inf),
  4. id=&quot;bnd&quot;)
  5. hole &lt;- data.frame(
  6. x = cos(seq(0, 2*pi, length.out = 360)),
  7. y = sin(seq(0, 2*pi, length.out = 360)),
  8. id=&quot;circle&quot;
  9. )
  10. porthole &lt;- rbind(bndBox,hole)
  11. ggplot() +
  12. # I want to be able to see this point
  13. geom_point(aes(x = 0,y = 0)) +
  14. # But not this point
  15. geom_point(aes(x = -1,y = 0)) +
  16. geom_polygon(data=porthole,
  17. aes(x = x, y = y, fill = id),
  18. inherit.aes = FALSE)

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

答案1

得分: 1

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

  1. library(ggplot2)
  2. bndBox &lt;- data.frame(x=c(-Inf,-Inf,Inf,Inf, -Inf),
  3. y=c(-Inf,Inf,Inf,-Inf, -Inf),
  4. id=&quot;bnd&quot;)
  5. bndBox &lt;- data.frame(x=c(-1,1,1,-1, -1),
  6. y=c(-1,-1,1,1, -1),
  7. id=&quot;bnd&quot;)
  8. hole &lt;- data.frame(
  9. x = cos(seq(0, 2*pi, length.out = 360)) * 0.95,
  10. y = sin(seq(0, 2*pi, length.out = 360)) * 0.95,
  11. id=&quot;circle&quot;
  12. )
  13. porthole &lt;- rbind(bndBox,hole)
  14. ggplot() +
  15. geom_polygon(data=porthole,
  16. aes(x = x, y = y), fill = &quot;red&quot;)+
  17. geom_point(aes(x = 0, y = 0)) +
  18. coord_fixed() +
  19. 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.

  1. library(ggplot2)
  2. bndBox &lt;- data.frame(x=c(-Inf,-Inf,Inf,Inf, -Inf),
  3. y=c(-Inf,Inf,Inf,-Inf, -Inf),
  4. id=&quot;bnd&quot;)
  5. bndBox &lt;- data.frame(x=c(-1,1,1,-1, -1),
  6. y=c(-1,-1,1,1, -1),
  7. id=&quot;bnd&quot;)
  8. hole &lt;- data.frame(
  9. x = cos(seq(0, 2*pi, length.out = 360)) * 0.95,
  10. y = sin(seq(0, 2*pi, length.out = 360)) * 0.95,
  11. id=&quot;circle&quot;
  12. )
  13. porthole &lt;- rbind(bndBox,hole)
  14. ggplot() +
  15. geom_polygon(data=porthole,
  16. aes(x = x, y = y), fill = &quot;red&quot;)+
  17. geom_point(aes(x = 0, y = 0)) +
  18. coord_fixed() +
  19. theme_void()

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

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

答案2

得分: 0

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

  1. library(ggplot2)
  2. library(sf)
  3. bndBox <- data.frame(x=c(-1,1,1,-1),
  4. y=c(1,1,-1,-1),
  5. id="bnd")
  6. hole <- data.frame(
  7. x = cos(seq(0, 2*pi, length.out = 360)),
  8. y = sin(seq(0, 2*pi, length.out = 360)),
  9. id="circle"
  10. )
  11. portholeSF <- st_sfc(
  12. st_polygon(
  13. list(
  14. hole = cbind(
  15. c(hole$x,hole$x[1]),
  16. c(hole$y,hole$y[1])
  17. ),
  18. bnd = cbind(
  19. c(bndBox$x,bndBox$x[1]),
  20. c(bndBox$y,bndBox$y[1])
  21. )
  22. )
  23. )
  24. )
  25. ggplot() +
  26. # 我想看到这个点
  27. geom_point(aes(x = 0,y = 0)) +
  28. # 但不想看到这个点
  29. geom_point(aes(x = -0.75,y = 0.75)) +
  30. 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:

  1. library(ggplot2)
  2. library(sf)
  3. bndBox &lt;- data.frame(x=c(-1,1,1,-1),
  4. y=c(1,1,-1,-1),
  5. id=&quot;bnd&quot;)
  6. hole &lt;- data.frame(
  7. x = cos(seq(0, 2*pi, length.out = 360)),
  8. y = sin(seq(0, 2*pi, length.out = 360)),
  9. id=&quot;circle&quot;
  10. )
  11. portholeSF &lt;- st_sfc(
  12. st_polygon(
  13. list(
  14. hole = cbind(
  15. c(hole$x,hole$x[1]),
  16. c(hole$y,hole$y[1])
  17. ),
  18. bnd = cbind(
  19. c(bndBox$x,bndBox$x[1]),
  20. c(bndBox$y,bndBox$y[1])
  21. )
  22. )
  23. )
  24. )
  25. ggplot() +
  26. # I want to see this point
  27. geom_point(aes(x = 0,y = 0)) +
  28. # But not this point
  29. geom_point(aes(x = -0.75,y = 0.75)) +
  30. 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:

确定