readRDS()加载额外的包
R中的readRDS()
函数在什么情况下尝试加载包/名称空间? 我很惊讶在新的R会议上看到以下内容:
> loadedNamespaces()
[1] "base" "datasets" "graphics" "grDevices" "methods" "stats"
[7] "tools" "utils"
> x <- readRDS('../../../../data/models/my_model.rds')
There were 19 warnings (use warnings() to see them)
> loadedNamespaces()
[1] "base" "class" "colorspace" "data.table"
[5] "datasets" "dichromat" "e1071" "earth"
[9] "evaluate" "fields" "formatR" "gbm"
[13] "ggthemes" "graphics" "grDevices" "grid"
[17] "Iso" "knitr" "labeling" "lattice"
[21] "lubridate" "MASS" "methods" "munsell"
[25] "plotmo" "plyr" "proto" "quantreg"
[29] "randomForest" "RColorBrewer" "reshape2" "rJava"
[33] "scales" "spam" "SparseM" "splines"
[37] "stats" "stringr" "survival" "tools"
[41] "utils" "wra" "wra.ops" "xlsx"
[45] "xlsxjars" "xts" "zoo"
如果任何这些新软件包不可用,则readRDS()
失败。
提到的19个警告是:
> warnings()
Warning messages:
1: replacing previous import ‘hour’ when loading ‘data.table’
2: replacing previous import ‘last’ when loading ‘data.table’
3: replacing previous import ‘mday’ when loading ‘data.table’
4: replacing previous import ‘month’ when loading ‘data.table’
5: replacing previous import ‘quarter’ when loading ‘data.table’
6: replacing previous import ‘wday’ when loading ‘data.table’
7: replacing previous import ‘week’ when loading ‘data.table’
8: replacing previous import ‘yday’ when loading ‘data.table’
9: replacing previous import ‘year’ when loading ‘data.table’
10: replacing previous import ‘here’ when loading ‘plyr’
11: replacing previous import ‘hour’ when loading ‘data.table’
12: replacing previous import ‘last’ when loading ‘data.table’
13: replacing previous import ‘mday’ when loading ‘data.table’
14: replacing previous import ‘month’ when loading ‘data.table’
15: replacing previous import ‘quarter’ when loading ‘data.table’
16: replacing previous import ‘wday’ when loading ‘data.table’
17: replacing previous import ‘week’ when loading ‘data.table’
18: replacing previous import ‘yday’ when loading ‘data.table’
19: replacing previous import ‘year’ when loading ‘data.table’
显然,它加载了一些类似于lubridate
和data.table
东西,随着它的发展而产生名称空间冲突。
FWIW, unserialize()
给出了相同的结果。
我真正想要的是加载这些对象,而不加载所有保存它们的人似乎已经加载的东西,这就是它看起来像在做的事情。
更新 :这里是对象x
中的类:
> classes <- function(x) {
cl <- c()
for(i in x) {
cl <- c(cl, if(is.list(i)) c(class(i), classes(i)) else class(i))
}
cl
}
> unique(classes(x))
[1] "list" "numeric" "rq"
[4] "terms" "formula" "call"
[7] "character" "smooth.spline" "integer"
[10] "smooth.spline.fit"
qr
来自quantreg
软件包,其余的都来自base
或stats
。
好。 这可能不是一个有用的答案(这将需要更多的细节),但我认为它至少是“在什么情况下”的一部分。
首先,我认为它不是特定于readRDS
但与任何可以load
的save
对象的工作方式相同。
“在什么情况下”部分:当保存的对象包含具有包/名称空间环境作为父项的环境时。 或者当它包含一个其环境是一个包/命名空间环境的函数时。
require(Matrix)
foo <- list(
a = 1,
b = new.env(parent=environment(Matrix)),
c = "c")
save(foo, file="foo.rda")
loadedNamespaces() # Matrix is there!
detach("package:Matrix")
unloadNamespace("Matrix")
loadedNamespaces() # no Matrix there!
load("foo.rda")
loadedNamespaces() # Matrix is back again
以下工作也是如此:
require(Matrix)
bar <- list(
a = 1,
b = force,
c = "c")
environment(bar$b) <- environment(Matrix)
save(bar, file="bar.rda")
loadedNamespaces() # Matrix is there!
detach("package:Matrix")
unloadNamespace("Matrix")
loadedNamespaces() # no Matrix there!
load("bar.rda")
loadedNamespaces() # Matrix is back!
我没有尝试过,但没有理由不能以saveRDS
/ readRDS
相同的方式工作。 解决方案:如果这对保存的对象没有坏处(例如,如果您确定实际上不需要这些环境),则可以通过替换它们来移除父环境,例如将parent.env
设置为使感。 所以使用上面的foo
,
parent.env(foo$b) <- baseenv()
save(foo, file="foo.rda")
loadedNamespaces() # Matrix is there ....
unloadNamespace("Matrix")
loadedNamespaces() # no Matrix there ...
load("foo.rda")
loadedNamespaces() # still no Matrix ...
我提出的一个令人痛苦的解决方法是通过一个令人讨厌的eval来清理它所附着的任何环境的对象:
sanitizeEnvironments <- function(obj) {
tc <- textConnection(NULL, 'w')
dput(obj, tc)
source(textConnection(textConnectionValue(tc)))$value
}
我可以取出旧对象,通过此函数运行它,然后再次对其执行saveRDS()
。 然后加载新的对象不会在我的命名空间上打击块。