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對象。創造這個對象的一個副本,然後改變副本中的構件,再將名字賦給這個副本。