我正在制作各种ggplot
在非常大的数据集上(比示例大得多)。我在 x 轴和 y 轴上创建了一个分箱函数,以便能够绘制如此大的数据集。
在下面的示例中,memory.size()
是在开始时记录的。然后将大数据集模拟为dt
. dt
's x2
是针对x1
与分箱。使用不同的子集重复绘图dt
。绘制对象的大小通过以下方式检查object.size()
并存储。创建绘图对象后,rm(dt)
被执行,然后是一个 doublegc()
。在此刻,memory.size()
再次被记录。最后,memory.size()
最后的内容与开头的内容进行比较并打印。
鉴于绘制对象的尺寸较小,预计memory.size()
最后的内容应该与开头的内容类似。But no. memory.size()
在我重新启动新的 R 会话之前不会再下降.
可重复的例子
library(data.table)
library(ggplot2)
library(magrittr)
# The binning function
# x = column name for x-axis (character)
# y = column name for y-axis (character)
# xNItv = Number of bin for x-axis
# yNItv = Number of bin for y-axis
# Value: A binned data.table
tab_by_bin_idxy <- function(dt, x, y, xNItv, yNItv) {
#Binning
xBreaks = dt[, seq(min(get(x), na.rm = T), max(get(x), na.rm = T), length.out = xNItv + 1)]
yBreaks = dt[, seq(min(get(y), na.rm = T), max(get(y), na.rm = T), length.out = yNItv + 1)]
xbinCode = dt[, .bincode(get(x), breaks = xBreaks, include.lowest = T)]
xbinMid = sapply(seq(xNItv), function(i) {return(mean(xBreaks[c(i, i+1)]))})[xbinCode]
ybinCode = dt[, .bincode(get(y), breaks = yBreaks, include.lowest = T)]
ybinMid = sapply(seq(yNItv), function(i) {return(mean(yBreaks[c(i, i+1)]))})[ybinCode]
#Creating table
tab_match = CJ(xbinCode = seq(xNItv), ybinCode = seq(yNItv))
tab_plot = data.table(xbinCode, xbinMid, ybinCode, ybinMid)[
tab_match, .(xbinMid = xbinMid[1], ybinMid = ybinMid[1], N = .N), keyby = .EACHI, on = c("xbinCode", "ybinCode")
]
#Returning table
return(tab_plot)
}
before.mem.size <- memory.size()
# Simulation of dataset
nrow <- 6e5
ncol <- 60
dt <- do.call(data.table, lapply(seq(ncol), function(i) {return(runif(nrow))}) %>% set_names(paste0("x", seq(ncol))))
# Graph plotting
dummyEnv <- new.env()
with(dummyEnv, {
fcn <- function(tab) {
binned.dt <- tab_by_bin_idxy(dt = tab, x = "x1", y = "x2", xNItv = 50, yNItv = 50)
plot <- ggplot(binned.dt, aes(x = xbinMid, y = ybinMid)) + geom_point(aes(size = N))
return(plot)
}
lst_plots <- list(
plot1 = fcn(dt),
plot2 = fcn(dt[x1 <= 0.7]),
plot3 = fcn(dt[x5 <= 0.3])
)
assign("size.of.plots", object.size(lst_plots), envir = .GlobalEnv)
})
rm(dummyEnv)
# After use, remove and clean up of dataset
rm(dt)
gc();gc()
after.mem.size <- memory.size()
# Memory reports
print(paste0("before.mem.size = ", before.mem.size))
print(paste0("after.mem.size = ", after.mem.size))
print(paste0("plot.objs.size = ", size.of.plots / 1000000))
我尝试对代码进行以下修改:
- Inside
fcn
,去除ggplot
并返回一个NULL
而不是绘图对象:内存泄漏完全消失了。但这不是解决方案。我需要剧情。
- 请求的绘图越少/传递的列越少/行越少
fcn
,内存泄漏越少。
- 如果我不创建任何子集并仅创建一个绘图对象(在示例中,我绘制了 3 个),那么内存泄漏也会存在。
- 流程结束后,甚至在我打电话之后
rm(list = ls())
,记忆仍然不可恢复。
我想知道为什么会发生这种情况以及如何在不影响我进行分箱图和子集的需要的情况下摆脱它dt
制作不同的情节。
感谢您的关注!