8.2 喀迈拉(no.21~no.30)
8.2.21 is.matrix
is.matrix
会造成惊喜,不仅因为在R
和S+
中会返回不同的答案。
> is.matrix(1:3)
[1] FALSE
> is.matrix(array(1:3, c(3,1)))
[1] TRUE
> is.matrix(array(1:3, c(3,1,1)))
[1] FALSE
> is.matrix(array(1:3, 3))
[1] FALSE
> is.matrix(data.frame(1:3))
[1] FALSE # would be TRUE in S+
> is.matrix(t(1:3))
[1] TRUE
is.matrix
中使用的"matrix"
的定义是一个维度是2的数组。注意到函数t
强制将一个非数组变为一个(列)矩阵然后进行转置。
一些人想要默认的矩阵。这是不可能的。R
是一个一般对象的语言,不是一个矩阵语言。
8.2.22 max
与pmax
我已不敢计算我遇到这种错误的次数了,或者我解决这种问题所花费的时间了。我仅仅思考总结在我非常清楚地知道max
和pmax
的区别(min
和pmin
)之后的时间。
回想一下第三轮回中有两种意义的向量化。max
和pmax
是分别不同的两种。
- max返回所有输入中最大的那个单独的数。
pmax返回一个对于输入中每个索引位置的最大的数的向量。
> max(1:5, 6:2) [1] 6 > pmax(1:5, 6:2) # 相同位置的最大数 [1] 6 5 4 4 5
"p"
在pmax
中的意思就是并行的意思(parallel)。
8.2.23 all.equal
返回令人惊讶的值
我们在第一轮回遇到了作为==
的替代品的all.equal
。数值错误造成"=="
很多情况下不会提供一个有用的结果。
if(all(x == y)) { # wrong if there is numerical error
if(all.equal(x, y)) { # WRONG, not FALSE when not equal
if(isTRUE(all.equal(x, y)) { # right
8.2.24 all.equal
并不相同
all.equal
的目的是比较那些可能对它们来说有模糊的记录。有时all.equal
所发现的模糊是让人惊讶的:
> all.equal(as.numeric(NA), 0/0)
[1] TRUE
The identical function allows for no fuzziness at all:
函数identical
不会造成模糊:
> identical(as.numeric(NA), 0/0)
[1] FALSE
8.2.25 identical
是真的真的相同
> xi <- 1:10
> yi <- 1:10
> identical(xi, yi[1:10])
[1] TRUE
> yi[11] <- 11
> identical(xi, yi[1:10])
[1] FALSE
> zi <- 1:10
> zi[11] <- 11L
> identical(xi, zi[1:10])
[1] TRUE
xi
是以integer
的形式存储。但是一旦yi
被添加了一个double
类型的值,它就以double
的形式存储了。
正如早都说过的那样,你不太肯能需要知道数字是怎么被存储的。如果你认为除了特殊的情况之外为什么会有这样的问题,那么或许你应该找到答案。
尽管identical
对于什么样的对象是相同的有着严格的要求,但是它也不至于坚持认为它们应该在内存中共享相同的位置。这基本上对R
来讲是一个陌生的概念。
8.2.26 =
不是<-
的代名词
操作符"="
在很多情况下和 "<-"
意味着相同的事情,但是有时也会不相同。
看看下边的代码:
foo(93, a = 47)
和
foo(93, a <- 47)
这两个命令会导致完全不同的结果。你不应该在给一个函数设置参数是使用"<-"
。
一个需要使用"<-"
而不是"="
的普遍情况是:
system.time(result <- my.test.function(100))
如果你在上边的命令中使用"="
,R
会认为你在试着设置system.time
中的result
参数,而这个参数并不存在。(如果system.time
不是你的常用函数,或许它应该是。)
标准建议是当你需要使用"<-"
就避免使用"="
即使这会让你多敲击一下键盘。无论如何,这是品味的问题(只要你知道它们的不同)。
8.2.27 复数算术
复数的优先权或许不是你期望的那样。看看:
> 1+3i - 3+5i
[1] -2+8i
8.2.28 复数不是数字
> is.numeric(1+3i)
[1] FALSE
复数也是数,但是在R
的眼里不是numeric
。为了在更广泛的意义上测试数字,你需要这样:
is.numeric(x) || is.complex(x)
8.2.29 非标准评估
有一些函数允许你输入对象的名字或者一个字符串类型的名字。比如:
help(subset)
使可以工作的,然而
help(’subset’)
才是真正有意义的。
做这个的函数意味着用于交互使用。允许有名字是有用的。如此的有用看起来好像是一个混合的祝福。很难讲节省网络时间的是去掉了两次键盘敲击还是之前造成的困惑。
如果这个命名的对象包含一个我们真的想要的字符串,一些函数给你想要的一些却不会。
foo <- ’subset’
help(foo) # gets help on subset
getAnywhere(foo) # finds foo, not subset
do.call(’getAnywhere’, list(foo)) # finds subset
一个非完全的对于参数没有标准评估的函数是:help
,rm
,save
,attach
,require
,library
,subset
,replicate
。
函数require
在参数character.only
上有一个编程安全机智。
require(foo) # load package foo
require(foo, character.only=FALSE) # load package foo
require(foo, character.only=TRUE) # load package named by foo
library
也是如此。
8.2.30 for的帮助
顺理成章地寻求for
的帮助文档是这样的:
?for
这个并没有起作用。使用函数help
似乎是一个不同的方式:
help(for)
替换如下(确保):
?’for’
help(’for’)