加快R

时间:2018-10-19 09:26:28

标签: r pdf ggplot2 heatmap

我试图在R中绘制由ggplot生成的大型热图。最终,我想使用Illustrator'抛光'该热图。

示例代码:

# Load packages (tidyverse)
library(tidyverse)

# Create dataframe
df <- expand.grid(x = seq(1,100000), y = seq(1,100000))

# add variable: performance
set.seed(123)
df$z <- rnorm(nrow(df))

ggplot(data = df, aes(x = x, y = y)) +
  geom_raster(aes(fill = z)) 

尽管我将图另存为矢量图像(.pdf;不是很大),但是打开时pdf的加载速度非常慢。我希望打开文件时会渲染数据框中的每个单独点。

我还阅读了其他使用image()来可视化矩阵的帖子(例如Data exploration in R: display heatmap of large matrix, quickly?),但是我想使用ggplot修改图像。

问题::如何加快该图的渲染速度?有没有办法(除了降低绘图的分辨率),同时保持图像矢量化,从而加快此过程?是否可以对矢量化ggplot进行下采样?

2 个答案:

答案 0 :(得分:3)

我尝试做的第一件事是stat_summary_2d来进行平均装箱,但是它似乎很慢,并且还在右侧和顶部边缘上产生了一些伪像:

library(tidyverse)
df <- expand.grid(x = seq(1,1000), y = seq(1,1000))
set.seed(123)
df$z <- rnorm(nrow(df))
print(object.size(df), units = "Mb")
#15.4 Mb

ggplot(data = df, aes(x = x, y = y, z = z)) +
  stat_summary_2d(bins = c(100,100)) +  #10x downsample, in this case
  scale_x_continuous(breaks = 100*0:10) +
  labs(title = "stat_summary_2d, 1000x1000 downsampled to 100x100")  

即使这比您建议的数据小得多,在我的计算机上绘制该图像仍需花费约3秒钟的时间,并且在顶部和右侧边缘都有伪影,我认为这是因为这些垃圾箱的边缘较小。更多变化。

enter image description here

当我尝试按您的要求尝试更大的网格时,它从那里开始变慢。

(顺便说一句,值得澄清的是,像PDF这样的矢量图形文件可以与光栅图形不同地进行调整大小,而不会降低分辨率。但是,在这种情况下,输出为10,000兆像素的光栅文件, far 超出了人类的感知极限,已被导出为矢量格式,其中每个“像素”在PDF中都变成了一个非常小的矩形。矢量格式的使用可能对某些异常情况很有用在某些情况下,例如您需要在不损失分辨率的情况下放大热图,而不是像足球场那样在巨大的表面上,但这听起来可能是错误的工作工具,因为您要放很多数据导入矢量文件中是不可察觉的。)

更有效的方法是在dplyr之前对ggplot进行平均。这样,我可以将一个10k x 10k的数组进行下采样100x,然后再发送到ggplot。这必然会降低分辨率,但是在这种用例中,保持分辨率超出了人类的感知能力之外,我并不理解。

这里有一些代码可以自己完成存储,然后绘制降采样的版本:

# Using 10k x 10k array, 1527.1 Mb when initialized
downsample <- 100
df2 <- df %>%
  group_by(x = downsample * round(x / downsample),
           y = downsample * round(y / downsample)) %>%
  summarise(z = mean(z))

ggplot(df2, aes(x = x, y = y)) +
  geom_raster(aes(fill = z)) +
  scale_x_continuous(breaks = 1000*0:10) +
  labs(title = "10,000x10,000 downsampled to 100x100")

enter image description here

答案 1 :(得分:2)

您的可复制示例仅显示噪音,因此很难知道您想要哪种输出。

一种方法是跟随@dww's suggestion并使用geom_hex显示汇总数据。

当您询问“是否可以对矢量化ggplot进行下采样吗?”时,另一种方法是在dplyr::sample_frac的data参数中使用dplyr::sample_ngeom_raster。不过,我必须比您的示例中的示例小一些,否则我将无法构建df。

library(tidyverse)

# Create dataframe
df <- expand.grid(x = seq(1,1000), y = seq(1,1000))

# add variable: performance
set.seed(123)
df$z <- rnorm(nrow(df))

ggplot(data = df, aes(x = x, y = y)) +
  geom_raster(aes(fill = z), . %>% sample_frac(0.1)) 

如果要从高分辨率ggplot对象开始,则可以达到相同的效果:

gg <- ggplot(data = df, aes(x = x, y = y)) +
  geom_raster(aes(fill = z)) 

gg$data <-  sample_frac(gg$data,0.1)
gg