首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对一层格点进行栅格化?

如何对一层格点进行栅格化?
EN

Stack Overflow用户
提问于 2017-11-10 12:25:43
回答 1查看 2.3K关注 0票数 7

Matplotlib允许对绘图中的单个元素进行栅格化,并将其保存为混合像素/矢量图形(.pdf) (参见这个答案)。如何在Rggplot2中实现相同的目标?

下面是一个玩具问题,在这个问题中,我只想对geom_point层进行扫描。

代码语言:javascript
复制
set.seed(1)
x <- rlnorm(10000,4)
y <- 1+rpois(length(x),lambda=x/10+1/x)
z <- sample(letters[1:2],length(x), replace=TRUE)

p <- ggplot(data.frame(x,y,z),aes(x=x,y=y)) +
  facet_wrap("z") +
  geom_point(size=0.1,alpha=0.1) +
  scale_x_log10()+scale_y_log10() +
  geom_smooth(method="gam",formula = y ~ s(x, bs = "cs"))
print(p)
ggsave("out.pdf", p)

当按原样保存为.pdf时,Adobe需要1s来呈现图形。下面可以看到一个.png版本:

当然,通过不绘制原始数据来避免这个问题是可能的。

EN

回答 1

Stack Overflow用户

发布于 2017-12-12 03:50:41

我想你已经准备好不回答这个问题了。你写:

我希望有一个答案可以为ggplot2提供一个扩展,该扩展允许导出具有栅格化层的地块,而对现有的绘图命令进行最小的更改,即作为geom_...命令的包装器,或者作为这些命令的附加参数,或者一个ggsave命令,该命令期望一个绘图命令的未评估部分的列表(每秒钟一次被光栅化),而不是链接问题中提供的一种麻烦的解决方法。

这是一项重大的开发工作,很容易需要高技能的开发人员进行几周或更多的工作。仅仅因为堆栈溢出问题,不太可能有人会这么做。代替一个有效的实现,我将在这里描述如何实现您所要求的内容,以及为什么它具有相当大的挑战性。

球员们

让我们从我们将要面对的关键球员开始。ggplot2库位于最高层。它使用数据帧并将它们转化为数字。不过,ggplot2本身对低级绘图一无所知。它只处理线条、多边形、文本等,并以图形对象(grobs)的形式提交给grid库。

grid库本身是一个相当高级别的库。它也不太了解低水平的绘画。它主要处理线,多边形,文本等,它把它交给一个R图形设备。设备进行实际绘图。

有许多不同的R图形设备。在R命令行中输入?Devices以查看不完整列表。有矢量图形设备(如pdfpostscriptsvg )、光栅设备(如pngjpegtiff )和交互设备(如X11quartz )。很明显,作为一个概念,栅格化只对矢量图形设备有意义,因为光栅设备以任何方式将所有东西都光栅化。重要的是,ggplot2grid都不知道或关心您当前使用的图形设备。它们处理可以在任何设备上绘制的图形对象。

理想高级界面

高级接口应该包含在rasterizelayer()函数中的一个选项ggplot2.通过这种方式,我们可以简单地编写,例如,geom_point(rasterize = TRUE)来对点层进行栅格化。这将透明地适用于所有geoms和stats,因为它们都调用了layer()

可能的实现

我看到了四种可能的实施途径,从最不可能到最少。

  1. 理想情况下,layer()函数只需将rasterize选项传递给grid库,grid库就会将其传递给图形设备,以告诉它要对哪些部分进行栅格化。这种方法需要对图形设备API进行重大更改。我不认为这会发生。至少在我有生之年没有。
  2. 或者,您可以编写一个新的grob类型,它可以接受任意的grob,并在图形设备上绘制grob时根据需要对其进行栅格化。这种方法不需要更改图形设备API,但需要详细了解grid库的低级实现。这也可能会使互动观看这些数字的速度非常缓慢。
  3. 对于2,一个稍微简单一些的替代方法是只对任意grob进行一次网格化,在grob构造上,然后在该grob绘制时重用。这将是相当快的互动图形设备,但绘图将被扭曲,如果纵横比是互动的改变。然而,由于这个功能的主要用途是生成pdf输出(我想),这个选项可能就足够了。
  4. 最后,在layer()函数中也可能发生栅格化,该函数可以简单地将一个普通的光栅grob放置到grob树中。该解决方案在技术上类似于在这里描述。技术,它与3没有太大区别。无论哪种方法,都需要编写代码来对grob树进行栅格化,然后用光栅grob替换它。

技术障碍

要对grob树的部分进行栅格化,我们必须将它们发送到R光栅图形设备进行渲染。然而,没有一个呈现到内存中。因此,必须将文件呈现为临时文件(例如,使用png()),然后将文件读入其中。这是可能的,但很丑陋。它还依赖于功能(如png()),而这些功能并不保证在每个R安装中都是可用的。

第二,要将grob树的部分呈现与整体呈现分开,除了当前打开的设备之外,我们还必须打开一个新的图形设备。这是可能的,但可能会导致意外的错误。我一直在处理这样的bug,例如,有关使用这种技术的代码的问题,请参见这里这里。无论是谁实现了栅格化功能,都必须处理这些问题。

最后,我们必须将栅格化代码输入到ggplot2库中,因为我们需要替换layer()函数,而且我认为没有办法从单独的包中做到这一点。考虑到光栅化解决方案将是多么棘手(见前两段),这可能是一项艰巨的任务。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47222764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档