8.1 幽灵(no.51~no.60)
8.1.51 非数字参数
> median(x)
Error in median.default(x) : need numeric data
如果你得到了一个这样的错误,很有可能x是一个因子类型。
8.1.52 函数round偶数取整
函数round()如果在数字的小数点最后是5就会取整到离这个数最近的整数(仅限于小数点后有一位)。
一些人对此感到惊奇。我对他们感到惊奇而感到惊奇—取整到偶数是很合理的啊。如果你想向上取整,自己写吧(也可以使用ceiling()和floor(),或者轻微地增大数的尺寸)。
有时你对这种情况不会发生而感到惊奇。这将是第一轮回的责任—看起来像最后是5的数可能并不是。
8.1.53 创建空的列表
你这样创建一个长度为500的数值向量:
numeric(500)
明显地,你会这样创建一个长度为500的列表:
list(500)
对吧?
错了。需要一点技巧:
vector('list', 500)
注意到这条命令表示了事实上列表在某种意义上就是向量。
当”vector”在不是列表的对象上使用时,它真的是”原子向量”的速记。
8.1.54 列表下标
my.list <- list(’one’, rep(2, 2))
以下两条命令是有区别的:
my.list[[1]]
和
my.list[1]
第一个好像是你想要的—列表的第一个组件。第二个是一个组件数为1,组件和原始列表的第一个组件相同的列表。
> my.list[[1]]
[1] "one"
> my.list[1]
[[1]]
[1] "one"
> is.list(my.list[[1]])
[1] FALSE
> is.list(my.list[1])
[1] TRUE
下边是一些建议:
- 单中括号总是给你和对象相同的类型—这个案例是列表。
- 双中括号没必要给你和对象相同的类型。
- 双中括号总是给你一条记录。
- 单中括号可以给你任何数量的记录。
8.1.55 NULL或者删除
如果你有一个列表并且你想其中的一个组件comp不在那里存在,你有一些选择。如果comp是那个组件的索引,那么最透明的方法是:
xl <- xl[-comp]
在任何情况下,你可以这样:
xl[[comp]] <- NULL
或者
xl[comp] <- NULL
前两个在S+中也能工作,但是最后一个不行。
如果你想这个组件在那里但是为NULL,这样:
xl[comp] <- list(NULL)
注意是单中括号,不是双中括号。
8.1.56 丢失的组件
for循环可以丢失正在修改的列表的组件
> xl.in <- list(A=c(a=3, z=4), B=NULL, C=c(w=8), D=NULL)
> xl.out <- vector(’list’, 4); names(xl.out) <- names(xl.in)
> for(i in 1:4) xl.out[[i]] <- names(xl.in[[i]])
> xl.out # not right
$A
[1] "a" "z"
$C
NULL
$D
[1] "w"
> xl.out2 <- lapply(xl.in, names)
> xl.out2
$A
[1] "a" "z"
$B
NULL
$C
[1] "w"
$D
NULL
注意我们的for循环得到的结果几乎确定的不是我们想要的。甚至可能不是我们预想的我们将会得到的。
当NULL是列表组件的构成时要注意了。使用lapply是个不错的选择。
8.1.57 合并列表
一些人对c()可以作用到list上感到愉快的惊奇。然后他们就滥用它。
> xlis <- list(A=1:4, B=c(’a’, ’x’))
> c(xlis, C=6:5)
$A
[1] 1 2 3 4
$B
[1] "a" "x"
$C1
[1] 6
$C2
[1] 5
可能不是你想要的,试试:
c(xlis, list(C=6:5))
8.1.58 消失的循环
考虑这个循环:
for(i in 1:10) i
这个循环不能工作是一个常见的抱怨,它没有做任何事情。事实上它工作地很好。问题是没有真正的操作在循环中包含。你可能想这样:
for(i in 1:10) print(i)
自动打印或者未分配的对象仅仅发生在最顶层。
8.1.59 有限的迭代
我最喜爱的技巧之一就是在迭代的时候给出最大界限而不是一个迭代序列:
for(i in trials) { ... }
而不是
for(i in 1:trials) { ... }
然后我好奇结果为何如此奇怪。
8.1.60 太多的迭代
for(i in 1:length(x)) { ... }
当x有一个正的长度时是好的。然而,如果x的长度是0时,R会做两次迭代。安全的方法是:
for(i in seq along(x)) { ... }
或者如果你想可以在S+中兼容:
for(i in seq(along=x)) { ... }