问题描述
R 中的 readRDS()
函数在什么情况下会尝试加载包/命名空间?我很惊讶地在新的 R 会话中看到以下内容:
Under what circumstances does the readRDS()
function in R try to load packages/namespaces? I was surprised to see the following in a fresh R session:
> 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()
就会失败.
If any of those new packages aren't available, the readRDS()
fails.
提到的 19 个警告是:
The 19 warnings mentioned are:
> 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
之类的内容,从而产生命名空间冲突.
So apparently it's loading something like lubridate
and then data.table
, generating namespace conflicts as it goes.
FWIW,unserialize()
给出相同的结果.
FWIW, unserialize()
gives the same results.
我真正想要的是加载这些对象,而不加载当时保存它们的人似乎已经加载的所有内容,这就是它正在做的事情.
What I really want is to load these objects without also loading everything the person who saved them seemed to have loaded at the time, which is what it sort of looks like it's doing.
更新:这里是对象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
.
qr
is from the quantreg
package, all the rest are from base
or stats
.
推荐答案
好的.这可能不是一个有用的答案(需要更多细节),但我认为这至少是在什么情况下......"部分的答案.
Ok. This may not be a useful answer (which would need more details) but I think it is at least an aswer to the "under what circumstances.." part.
首先,我认为它不是特定于 readRDS
,而是与任何可以 load
的 save
对象一样工作> 已编辑.
First of all, I think it is not specific to readRDS
but works the same way with any save
'd objects that can be load
'ed.
在什么情况下"部分:当保存的对象包含具有包/命名空间环境作为父级的环境时.或者当它包含一个环境为包/命名空间环境的函数时.
The "under what circumstances" part: when the saved object contains an environment having a package/namespace environment as a parent. Or when it contains a function whose environment is a package/namespace environment.
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
,
I haven't tried but there's no reason why it shouldn't work the same way with saveRDS
/readRDS
. And the solution: if that does no harm to the saved objects (i.e., if you're sure that the environments are actually not needed), you can remove the parent environments by replacing them e.g. by setting the parent.env
to something that makes sense. So using the foo
above,
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 ...
这篇关于readRDS() 加载额外的包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!