具有共享数据的多个 ggplot2 图
Multiple ggplot2 graphs with shared Data
如何在回收数据时制作相同数据的多个图,但因不同因素(列)而着色不同?这是 gridExtra
与 cowplot
的不同之处吗?
Objective:
我的objective是为了直观比较高效聚类相同数据的不同结果。
我目前认为直观地比较 2-4 个聚类算法的最简单方法是将它们绘制成彼此相邻的图。
因此,如何将相同的数据并排绘制成不同的颜色?
Challenge/Specifications: 性能很重要。我要制作大约 30,000 个图表,每个图表有 450 - 480 个点。关键是数据是"recycled."
我可以使用包 cowplot
和 gridExtra
并排绘制它们。我今天刚开始使用 gridExtra
,但它似乎可以回收数据,而且对我来说比 cowplot 更好。 更新: u/eipi10 证明如果我在绘图前收集列,facet_wrap
可以工作。
设置
#Packages
library(ggplot2)
library(cowplot)
library(gridExtra)
library(pryr) #memory profile
#Data creation
x.points <- c(1, 1, 1, 3, 3, 3, 5, 5, 5)
y.points <- c(1, 3, 5, 1, 3, 5, 1, 3, 5)
cl_vert <- c("A", "A", "A", "B", "B", "B", "C", "C", "C")
cl_hoz <- c("A", "B", "C", "A", "B", "C", "A", "B", "C")
cl_cent <- c("A","A","A","A", "B", "A","A","A","A")
df <- data.frame(x.points, y.points, cl_vert, cl_hoz, cl_cent)
绘制它们
#Graph function and individual plots
graph <- function(data = df, Title = "", color.by, legend.position = "none"){
ggplot(data, aes(x = `x.points`, y = `y.points`)) +
geom_point(aes(color = as.factor(color.by))) + scale_color_brewer(palette = "Set1") +
labs(subtitle = Title, x = "log(X)", y = "log(Y)", color = "Color" ) +
theme_bw() + theme(legend.position = legend.position)
}
g1 <- graph(Title = "Vertical", color.by = cl_vert)
g2 <- graph(Title = "Horizontal", color.by = cl_hoz)
g3 <- graph(Title = "Center", color.by = cl_cent)
#Cowplot
legend <- get_legend(graph(color.by = cl_vert, legend.position = "right")) #Not a memory waste
plot <- plot_grid(g1, g2, g3, labels = c("A", "B", "C"))
title <- ggdraw() + draw_label(paste0("Data Ex ", "1"), fontface = 'bold')
plot2 <- plot_grid(title, plot, ncol=1, rel_heights=c(0.1, 1)) # rel_heights values control title margins
plot3 <- plot_grid(plot2, legend, rel_widths = c(1, 0.3))
plot3
#gridExtra
plot_grid.ex <- grid.arrange(g1, g2, g3, ncol = 2, top = paste0("Data Ex ", "1"))
plot_grid.ex
pryr 的内存使用情况
#Comparison
object_size(plot_grid) #315 kB
object_size(plot3) #1.45 MB
#Individual objects
object_size(g1) #756 kB
object_size(g2) #756 kB
object_size(g3) #756 kB
object_size(g1, g2, g3) #888 kB
object_size(legend) #43.6 kB
其他问题:
写完这道题,提供了样例数据,我才想起[=13=],试了一下,好像比它的成分图合并数据占用内存少。我认为 g1、g2 和 g3 除了着色分配外共享相同的数据,这就是为什么各个组件和总对象大小之间存在大约 130 kB 的差异。为什么 plot_grid 比 space 占用更少? ls.str(plot_grid)
似乎没有显示 g1、g2 和 g3 的任何合并。我最好的选择是使用 lineprof()
和 运行 逐行比较吗?
我的来源skimmed/read/consulted:
- http://adv-r.had.co.nz/memory.html #没完全看懂
- Add a common Legend for combined ggplots #稍后修复 gridExtra
请多多包涵,因为我是一名新程序员(12 月才真正开始编写脚本);我还不了解所有技术细节,但我想了解。
如果您将数据转换为长格式,分面将在这里起作用。这是一个例子:
library(tidyverse)
df %>% gather(method, cluster, cl_vert:cl_cent) %>%
ggplot(aes(x = x.points, y = y.points)) +
geom_point(aes(color = cluster)) +
scale_color_brewer(palette = "Set1") +
theme_bw() +
facet_wrap(~ method)
如果您追求性能提升,请不要使用任何这些包,包括 ggplot2。 gridExtra、cowplot 和其他人总是会让事情变得更慢,而且它们在任何意义上都不会 "recycle" 数据(不清楚你的意思)。
我建议在 ggplot2 之外进行所有耗时的数据处理,并绘制已经更接近最终映射的结果(即已经分配了颜色组等)。您可能会发现 ggplot2 对您的应用程序来说变得过分和缓慢(格子通常更快,底图也是如此)。
如果你真的想要共享数据,我认为像d3.js这样的东西可能会让你最接近这个目标,尽管它只会将数据重复留给浏览器在渲染时做的事情。一旦数据点呈现在屏幕上,它们就必须是独立的和重复的,所以问题是在管道中的什么地方最方便和最有效地做到这一点。
如何在回收数据时制作相同数据的多个图,但因不同因素(列)而着色不同?这是 gridExtra
与 cowplot
的不同之处吗?
Objective: 我的objective是为了直观比较高效聚类相同数据的不同结果。 我目前认为直观地比较 2-4 个聚类算法的最简单方法是将它们绘制成彼此相邻的图。
因此,如何将相同的数据并排绘制成不同的颜色?
Challenge/Specifications: 性能很重要。我要制作大约 30,000 个图表,每个图表有 450 - 480 个点。关键是数据是"recycled."
我可以使用包 cowplot
和 gridExtra
并排绘制它们。我今天刚开始使用 gridExtra
,但它似乎可以回收数据,而且对我来说比 cowplot 更好。 更新: u/eipi10 证明如果我在绘图前收集列,facet_wrap
可以工作。
设置
#Packages
library(ggplot2)
library(cowplot)
library(gridExtra)
library(pryr) #memory profile
#Data creation
x.points <- c(1, 1, 1, 3, 3, 3, 5, 5, 5)
y.points <- c(1, 3, 5, 1, 3, 5, 1, 3, 5)
cl_vert <- c("A", "A", "A", "B", "B", "B", "C", "C", "C")
cl_hoz <- c("A", "B", "C", "A", "B", "C", "A", "B", "C")
cl_cent <- c("A","A","A","A", "B", "A","A","A","A")
df <- data.frame(x.points, y.points, cl_vert, cl_hoz, cl_cent)
绘制它们
#Graph function and individual plots
graph <- function(data = df, Title = "", color.by, legend.position = "none"){
ggplot(data, aes(x = `x.points`, y = `y.points`)) +
geom_point(aes(color = as.factor(color.by))) + scale_color_brewer(palette = "Set1") +
labs(subtitle = Title, x = "log(X)", y = "log(Y)", color = "Color" ) +
theme_bw() + theme(legend.position = legend.position)
}
g1 <- graph(Title = "Vertical", color.by = cl_vert)
g2 <- graph(Title = "Horizontal", color.by = cl_hoz)
g3 <- graph(Title = "Center", color.by = cl_cent)
#Cowplot
legend <- get_legend(graph(color.by = cl_vert, legend.position = "right")) #Not a memory waste
plot <- plot_grid(g1, g2, g3, labels = c("A", "B", "C"))
title <- ggdraw() + draw_label(paste0("Data Ex ", "1"), fontface = 'bold')
plot2 <- plot_grid(title, plot, ncol=1, rel_heights=c(0.1, 1)) # rel_heights values control title margins
plot3 <- plot_grid(plot2, legend, rel_widths = c(1, 0.3))
plot3
#gridExtra
plot_grid.ex <- grid.arrange(g1, g2, g3, ncol = 2, top = paste0("Data Ex ", "1"))
plot_grid.ex
pryr 的内存使用情况
#Comparison
object_size(plot_grid) #315 kB
object_size(plot3) #1.45 MB
#Individual objects
object_size(g1) #756 kB
object_size(g2) #756 kB
object_size(g3) #756 kB
object_size(g1, g2, g3) #888 kB
object_size(legend) #43.6 kB
其他问题:
写完这道题,提供了样例数据,我才想起[=13=],试了一下,好像比它的成分图合并数据占用内存少。我认为 g1、g2 和 g3 除了着色分配外共享相同的数据,这就是为什么各个组件和总对象大小之间存在大约 130 kB 的差异。为什么 plot_grid 比 space 占用更少? ls.str(plot_grid)
似乎没有显示 g1、g2 和 g3 的任何合并。我最好的选择是使用 lineprof()
和 运行 逐行比较吗?
我的来源skimmed/read/consulted:
- http://adv-r.had.co.nz/memory.html #没完全看懂
- Add a common Legend for combined ggplots #稍后修复 gridExtra
请多多包涵,因为我是一名新程序员(12 月才真正开始编写脚本);我还不了解所有技术细节,但我想了解。
如果您将数据转换为长格式,分面将在这里起作用。这是一个例子:
library(tidyverse)
df %>% gather(method, cluster, cl_vert:cl_cent) %>%
ggplot(aes(x = x.points, y = y.points)) +
geom_point(aes(color = cluster)) +
scale_color_brewer(palette = "Set1") +
theme_bw() +
facet_wrap(~ method)
如果您追求性能提升,请不要使用任何这些包,包括 ggplot2。 gridExtra、cowplot 和其他人总是会让事情变得更慢,而且它们在任何意义上都不会 "recycle" 数据(不清楚你的意思)。
我建议在 ggplot2 之外进行所有耗时的数据处理,并绘制已经更接近最终映射的结果(即已经分配了颜色组等)。您可能会发现 ggplot2 对您的应用程序来说变得过分和缓慢(格子通常更快,底图也是如此)。
如果你真的想要共享数据,我认为像d3.js这样的东西可能会让你最接近这个目标,尽管它只会将数据重复留给浏览器在渲染时做的事情。一旦数据点呈现在屏幕上,它们就必须是独立的和重复的,所以问题是在管道中的什么地方最方便和最有效地做到这一点。