8.1 幽灵(no.31~no.40)
8.1.31 多重比较
0 < x < 1
看起来是个合理的方法来测试x是否在0和1之间。可R并不这么认为。R是这么想的:
0 < x & x < 1
8.1.32 命名覆盖
默认的T和F分别分配给TRUE和FALSE。然而,它们也可以被用来命名对象(S+中不可以)。你可以考虑一下建议:
- 最好使用TRUE和FALSE,而不是T和F。
- 最好不要使用T和F来给对象命名,以免和没有遵从建议1的情况而产生碰撞。
最好避免使用常用函数名字来命名对象。比如c和t。并且不要叫你的矩阵matrix:
fortune(’dog’)
通常情况下覆盖对象仅仅会造成困惑。但是,如果你将你自己的函数的名称覆盖到一个常用的函数上,无异于自杀。
> c <- function(x) x * 100
> par(mfrow=c(2, 2))
Error in c(2, 2) : unused argument(s) (2)
如果你遇到了一个极度奇怪的错误,可能就是名称覆盖的问题。在已经存在的情况下规避这个名称:
find(’c’)
如果你知道哪个函数出现了问题。可以这样查找具体错误:
conflicts(detail=TRUE)
另外一个可能的方法是使用--vanilla
启动R。
8.1.33 排序
当函数sort()不能实现你所想要的排序功能时,函数order()或许可以助阵。函数order()使用场合:
- 对矩阵的行或者数据框进行排序。
- 对基于另外一个向量值的向量进行排序。
- 打破与其他变量的关系。
8.1.34 sort.list()并不是适用于列表
不要认为sort.list()就是给列表排序。你个笨蛋。
> sort(as.list(1:20))
Error in sort.int(x, na.last = na.last, ...) :’x’ must be atomic
> sort.list(as.list(1:20))
Error in sort.list(as.list(1:20)) : ’x’ must be atomic Have you called ’sort’ on a list?
如果你想对你的列表进行排序,你需要构造你自己的函数去实现了。
8.1.35 搜索列表改组
attach和load在目的上非常相似,但效果上却不同。attach在搜索列表中新建了一个目录而load将所包含的内容全部加入到了全局环境中(搜索列表的第一位)。
通常情况下,attach是将组对象之间区分的好的方法。然而,如果你改变了工作目录并且需要一个已经存在的.RData,这时候load是你的选择。
下边是一个脚本(你不像要的):
- 目录project1下存在一个.RData。
- 你在其他目录下打开了一个R,并且将工作目录切换到project1。
- 全局环境来自初始目录。
- 你attach这个在project1下的.RData。
- 你做了一些工作,退出并且保存了工作空间。
- 你仅仅是擦拭了project1的原始.RData,丢失了刚才的数据。
8.1.36 source 和 attach 或者 load
attach和load都可以将R对象加入搜索列表。函数source也可以,但是在起点是以代码的形式创建对象而不是那个实际的对象。
你应该按照管理进行操作。R代码的扩展名是”.R”。其他扩展名包括”.q”,”.rt”,”.Rscript”。
R对象的文件扩展名包括”.rda”,”.RData”。
8.1.37 字符串不是名字(I)
如果你有一个包含一个对象名字的字符型字符串,并且你想得到这个对象,使用get():
funs <- c(’mean’, ’median’)
get(funs[2])(data)
如果你发现as.name()并且觉得这个可以解决你的问题,你是正确的但是得再进一步:
eval(as.name(funs[2]))(data)
8.1.38 获得一个构件
函数get()非常有用,但并不是千里眼。如果你这样:
get(’myobj$comp’)
它会认为你需要一个名字为”myobj$comp
“的对象。如果你想要myobj中的comp构件,你需要这样:
get(’myobj’)$comp
8.1.39 字符串不是名字(II)
如果在一个列表中,你有一个你想提取的构件,它的名字是一个字符串形式,你不可以使用”$”,你需要使用”[[“:
> mylist <- list(aaa=1:5, bbb=letters)
> subv <- ’aaa’
> mylist$subv
NULL
> # the next three lines are all the same
> mylist$aaa
[1] 1 2 3 4 5
> mylist[[’aaa’]]
[1] 1 2 3 4 5
> mylist[[subv]]
[1] 1 2 3 4 5
8.1.40 字符串不是名字(III)
如果你使用paste()创造了一个是对象名字的字符串,你不可以在赋值的左边:
> paste(’x’, 1, sep=’’) <- 3:5
Error: Target of assignment expands to non-language object
但是assign可以这样:
for(i in 1:n) assign(paste(’obj’, i, sep=’.’), mylist[[i]])
警告:这样的操作会让你回到第三轮回(向量化失败—这是一个反向量化的操作)或者第六轮回的异教徒。
你可以看到get(),将”myobj$comp”作为名字并不会得到你想要的结果—它仅仅会创造一个非标准名字的对象而不是修改myobj的comp对象。创造这个对象的一个副本,然后改变副本中的构件,再将名字赋给这个副本。