如何将裁剪蒙版应用于ggplot中的geom? [英] How to apply a clipping mask to geom in a ggplot?

查看:112
本文介绍了如何将裁剪蒙版应用于ggplot中的geom?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对ggplot中的几何图形应用剪贴蒙版,以掩盖部分数据,但保持轴,网格,其他几何图形和图例可见.我不想创建一个特定的图,因此,我不希望使用掩盖该图某些部分的多边形的变通方法.

I am trying to apply a clipping mask to a geom from a ggplot to mask part of the data, but keep the axis, the grid, other geoms and the legend visible. I do not want to create a specific plot, and therefore I am not looking for a work-around with polygons masking some parts of the plot.

这是我想模仿的设计(面具,不一定是主题,我现在要怎么做):

This is the kind of design I would like to emulate (the mask, not necessarily theme, I now how to do that):

()

另请参见此示例

有人认为我可以过滤定义遮罩的多边形中不包含的数据.但是,尽管它适用于点,并且可以适用于多边形/线状对象,但是适用于栅格(边界不会完全遵循非垂直或非水平线). 所以我尝试了以下方法:

One could argue that I could filter the data that is not contained in the polygon that defines the mask. But, while it works for point, and can work for polygon/line-like objects, it does for rasters (the border would not exactly follow non-vertical or non-horizontal lines). So I tried the following:

library(ggplot2)
library(gridSVG)
library(grImport)

# Create a plot
p <- ggplot(diamonds[1:300,], aes(carat, price)) + geom_point(aes(colour = cut))

# And a clipping mask
pg <- polygonGrob(c(.7, 0, 0, 1, 1),
              c(0, .7, 1, 1, 0))
cp <- clipPath(pg)

我能够使用软件包gridSVG定义ggplotGrob()一起使用R2015-grid/grid-slides.html#1"rel =" noreferrer>此处).我无法将剪切蒙版应用到grob:

I was able to use the packages gridSVG to define a clipping mask, but I have difficulties applying it on a ggplot object, even after extracting the grob (see resource here) with ggplotGrob(). I was not able to apply the clipping mask to the grob:

g <-  ggplotGrob(p) # store the plot as a grob

registerClipPath("mask", cp)
g_clipped <- clipPath(g)

gridsvg(name = "test_c2.svg")
grid.draw(clipPathGrob(g_clipped, cp)$grob)
dev.off()

我的直觉是应该绘制g_clipped,但是我不能grid.draw(),因为它是一个clipPath对象.而grid.draw() 此处写的线显示未屏蔽的情节.我想我不太了解clipPath对象的功能.

My intuition was that the g_clipped should be plotted, but I couldn't grid.draw() it, since its a clipPath object. And the grid.draw() line written here show the plot not masked. I think I don't quite grasp how the clipPath objects function.

函数grobify()听起来可能对没有gridSVG的替代方法有所帮助,请参见

The function grobify() sounds like it could help for an alternative appraoch without gridSVG, see details here, but I do not understand the quite minimalistic documentation.

由于我什至无法将剪切蒙版应用于整个情节,因此我的目标远非如此.

Since I cannot even apply the clipping mask to the whole plot, I am far for my objective.

如果您可以帮助我了解如何从gridSVG应用剪切蒙版,或者有替代解决方案将剪切蒙版应用于特定的几何图形,请告诉我.

If you can help me understand how to apply the clipping mask from gridSVGor have an alternative solution to apply a clipping mask to specific geoms, please let me know.

推荐答案

以下是网格解决方案,但是非常变通.它显示了如何将非矩形裁剪区域应用于ggplot,以便裁剪绘图中的一组点.您的尝试并不太错.需要注意的几点:

The following is a grid solution, but very much a work-around. It shows how to apply a non-rectangular clipping region to a ggplot, so that one set of points in your plot is clipped. You weren't too far wrong in your attempt. A couple of points to note:

  1. 您需要grid.force() ggplotGrob对象,以便grid可以看到grobs.
  2. 请勿将ggplot grob定义为剪切路径-剪切路径为多边形.
  3. 将剪切路径应用于ggplot的绘图面板中的grob点.这意味着绘图面板中的其他对象(面板背景和网格线)不会被剪切.仅数据点被裁剪.
  1. You need to grid.force() the ggplotGrob object so the grid can see the grobs.
  2. Do not define the ggplot grob as a clipping path - the clipping path is the polygon.
  3. The clipping path is applied to the points grob within the plot panel of the ggplot. This means that other objects in the plot panel, the panel background and grid lines, do not get clipped. Only the data points are clipped.

我在绘图中添加了一条蓝线,以表明该线也不需要修剪;但可以根据需要进行裁剪.

I've added a blue line to the plot to show that the line too does not need to be clipped; but can be clipped if desired.

也有注释的代码行,当未注释时,将绘制剪切区域,并将网格线和点移动到前面(即,较深的灰色剪切区域的前面).

There are also commented lines of code that, when uncommented, will draw the clipping region, and move the grid lines and points to the front (that is, in front of the darker grey clipping region).

library(ggplot2)
library(gridSVG)
library(grid)

# Open the graphics device
gridsvg(name = "test.svg")

# Create a plot
p <- ggplot(diamonds[1:300, ], aes(carat, price)) + 
       geom_point(aes(colour = cut)) +
       geom_line(data = data.frame(x = c(.3, .9), y = c(500, 2500)), aes(x,y), col = "skyblue", size = 2)
g <- ggplotGrob(p) # Store the plot as a grob


g = grid.force(g)  # So that grid sees all grobs
grid.draw(g)       # Draw the plot

# Define the clipping path
pg <- polygonGrob(c(.7, 0, 0, 1, 1),
                  c(0, .7, 1, 1, 0))
# The clipping path can be nearly any shape you desire. 
# Try this for a circular region
# pg = circleGrob(x = .5, y = .6, r = .5)
cp <- clipPath(pg)

# Add the clipping path to the points grob.
# That is, only the points inside the polygon will be visible,
# but the background and grid lines will not be clipped. 
# Nor will the blue line be clipped.
# grid.ls(g)     # names of the grobs
seekViewport(grep("panel.[0-9]", grid.ls(g)$name, value = TRUE))
grid.clipPath("points", cp, grep = TRUE)   

# To clip the blue line, uncomment the next line
# grid.clipPath("GRID.polyline", cp, grep = TRUE)       

# To show the clipping region,    
# uncomment the next two lines.
# showcp = editGrob(pg, gp = gpar(fill = rgb(0, 0, 0, 0.05), col = "transparent"))
# grid.draw(showcp)

# And to move the grid lines, remaining data points, and blue line in front of the clipping region,
# uncomment the next five lines
# panel = grid.get("panel", grep = TRUE)   # Get the panel, and remove the background grob
# panel = removeGrob(panel, "background", grep = TRUE)

# grid.remove("points", grep = TRUE)     # Remove points and grid lines from the rendered plot
# grid.remove("line", grep = TRUE, global = TRUE)

# grid.draw(panel)     # Draw the edited panel - on top of the clipping region 


# Turn off the graphics device
dev.off()

# Find text.svg in your working directory







编辑使用绘制数据点的坐标系定义裁剪区域.

Edit Defining the clipping region using the coordinate system in which the data points were drawn.

library(ggplot2)
library(gridSVG)
library(grid)

# Open the graphics device
gridsvg(name = "test.svg")

# Create a plot
p <- ggplot(diamonds[1:300, ], aes(carat, price)) + 
       geom_point(aes(colour = cut)) +
       geom_line(data = data.frame(x = c(.3, .9), y = c(500, 2500)), aes(x,y), col = "skyblue", size = 2)
g <- ggplotGrob(p) # Store the plot as a grob


g = grid.force(g)  # So that grid sees all grobs
grid.draw(g)       # Draw the plot

# Get axis limits (including any expansion)
axis.limits = summarise_layout(ggplot_build(p))[1, c('xmin', 'xmax', 'ymin', 'ymax')]

# Find the 'panel' viewport,
# then push to a new viewport, 
# one that exactly overlaps the 'panel' viewport,
# but with limits on the x and y scales that are the same
# as the limits for the original ggplot. 
seekViewport(grep("panel.[0-9]", grid.ls(g)$name, value = TRUE))
pushViewport(dataViewport(xscale = axis.limits[1, 1:2],
                          yscale = axis.limits[1, 3:4]))

# Define the clipping path
 pg <- polygonGrob(x = c(.6,   0.3, .3,   .8,   1.2), 
                   y = c(500, 1500, 2900, 2900, 1500), 
                   default.units="native")
cp <- clipPath(pg)

# Add the clipping path to the points grob.
# That is, only the points inside the polygon will be visible,
# but the background and grid lines will not be clipped. 
# Nor will the blue line be clipped.
# grid.ls(g)     # names of the grobs

grid.clipPath("points", cp, grep = TRUE)   

# To clip the blue line, uncomment the next line
 grid.clipPath("GRID.polyline", cp, grep = TRUE)       

# To show the clipping region. 
 showcp = editGrob(pg, gp = gpar(fill = rgb(0, 0, 0, 0.05), col = "transparent"))
 grid.draw(showcp)

# And to move the grid lines and remaining data points in front of the clipping region.
 panel = grid.get("panel", grep = TRUE)   # Get the panel, and remove the background grob
 panel = removeGrob(panel, "background", grep = TRUE)

 grid.remove("points", grep = TRUE)     # Remove points and grid lines from the rendered plot
 grid.remove("line", grep = TRUE, global = TRUE)

 grid.draw(panel)     # Draw the edited panel - on top of the clipping region 


# Turn off the graphics device
dev.off()

# Find text.svg in your working directory

这篇关于如何将裁剪蒙版应用于ggplot中的geom?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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