R的诡异错误(2)
A pitfall in R
R里面的陷阱一个接一个,继上次说的诡异错误,最近我又跌进了另一个坑。
先创造一个叫df的data.frame, 如下所示:
options(stringsAsFactors = FALSE) df <- data.frame( group = c("group1", "group2"), val = c(100, 9) ) df # df content: # # group val #1 group1 100 #2 group2 9
我们统计一下val列在每组(group)的均值:
## get mean value per group library(plyr) res <- ddply(df, .(group), function(x) { c(group = unique(x$group), val = mean(x$val)) }) res
res的结果如下:
> res group val 1 group1 100 2 group2 9 > res[1,2] > res[2,2] [1] FALSE
困惑的地方来了,res[1,2]显示的是“100”, res[2,2]现实的是“9”, 为什么res[1,2] > res[2,2]的结果是FALSE?
R肯定是认为100比9大。这显然是不对的。
那上面哪个地方有陷阱呢?再仔细看一下高亮显示的两行,看出问题了么?
## get mean value per group res <- ddply(df, .(group), function(x) { c(group = unique(x$group), val = mean(x$val)) })
陷阱在于第3-4行,当用c()来构造一个向量时,val被自动从数值型转成字符型。也就是说,存储的是“100”和“9”,不是100和9。
在字符型数值的比较中,“9”是会比“100”大的。因此order输出的是2 1.
从这个坑里爬出来,不由得吐槽一下,R的自动类型转换能减少程序的代码量,但是这种类型转换很容易引入错误。
也就是说R编程时不需要程序员去检查类型,但在底层R会自动的(有时也是自作聪明的)转换类型。
这就要求程序员额外费心考虑类型之间的自动转换,实际上加重了编程的负担。
如果不然,程序员放任R做自动的类型匹配和转换,就可能得到错误的结果,这在科学研究中实在是很危险。
既然R的坑这么多,我想过去试试新出的Julia或者Go语言。可惜现在这些语言都没有很好的支持统计计算,比如Julia目前缺少对缺失数据(missing data)的支持,
比较有希望的NumPy写起来语法繁杂,近期吸引不到大多数的统计学家(统计的用户太少,机器学习的用户多)。
要是能有一种计算工具,可以让统计学家很容易的使用,同时又有较强的类型系统,还能把大多数R包迁移过去,那这种工具必有远大前程。