一个公式可以很容易地由字符串创建:
> myvars <- paste(’V’, 1:9, sep=’’) > myvars [1] "V1" "V2" "V3" "V4" "V5" "V6" "V7" "V8" "V9" > as.formula(paste(’y ~ ’, paste(myvars[c(3,5,8)],collapse=’ + ’))) y ~ V3 + V5 + V8你或许想制造一个plot或者其他输出来描述已经使用的数据。你或许这样做:
myfun <- function(x, ...) { plot(x, main=x, ...) }但是这个将会产生一个不那么令人愉快的主题。函数substitute()搭配函数deparse()或许是你所寻找的:
myfun2 <- function(x, ...) { plot(x, main=deparse(substitute(x)), ...) }如果你没有在”else”出现的的地方期待”else”,那你将会在哪里期待呢?
或许你会想着R给你这样一个错误信息好滑稽,R却想着你更滑稽期望你所做的工作起来。当R得到一个完整的语句后就会输入,进行评估,再进行更多的输入。下边是如何得到那个错误的:
if(any(abs(x) > 1)) atan(x) else asin(x)当R到达第一行的最后,这是一个相当完美的语句,所以R对其进行评估。然后它发现了一条以”else”开始的语句—没有意义了。适当的格式是关键。如果方便的化,你可以将整个代码放在一行:
if(any(abs(x) > 1)) atan(x) else asin(x)或者,使用大括号(适当的地方放置”else”):
if(any(abs(x) > 1)) { atan(x) } else { asin(x) }默认情况下,当下标化为1时,数组的维度将会被降低。使用drop=FALSE的下标化会重载默认情况。
NOTE: 没有在函数中使用drop=FALSE是错误的主要来源。你仅仅是测试了函数当下标大于1的情况。当下标为1时,函数就不行了—在此地降维一个矩阵是被期望的并且被简单的向量替代。 NOTE: 没有在函数中使用drop=FALSE是错误的主要来源(再次强调)。
函数drop()对数据框不起作用。如果你想在数据框上降维,你需要使用带有drop参数的下标化操作。 在数据框上降维操作将会导致意外情况(但是符合逻辑)。
> xdf <- data.frame(a=1:2, b=c(’v’, ’w’)) > xdf[1,] # data frame a b 1 1 v > drop(xdf[1,]) # data frame a b 1 1 v > xdf[1, , drop=TRUE] # list $a [1] 1 $b [1] v Levels: v w > xdf[,1] # numeric vector [1] 1 2 > xdf[, 1, drop=FALSE] # data frame a 1 1 2 2 > drop(xdf[, 1, drop=FALSE]) # data frame a 1 1 2 2在降维过程中数据框的行名丢失了:
> xdf2 <- data.frame(a=1:4, b=42:45,row.names=LETTERS[1:4]) > xdf2[, 1] [1] 1 2 3 4 > as.matrix(xdf2)[, 1] A B C D 1 2 3 4首先强制转换成矩阵将会保留行名,但是当数据框的列属性是多种的话很有可能不会得到正确的值。
> xdf2b <- data.frame(a=1:4,b=letters[21:24],row.names=LETTERS[1:4]) > as.matrix(xdf2b)[,1] A B C D "1" "2" "3" "4" > drop(as.matrix(xdf2b[, 1, drop=FALSE])) A B C D 1 2 3 4最后一行代码,尽管有点复杂,但却会给你正确的答案。
如果你在apply上使用一个返回一个向量的函数,这会变成结果的第一个维度。这很可能不是当你在行上操作时天真地认为的结果。
> matrix(15:1, 3) [,1] [,2] [,3] [,4] [,5] [1,] 15 12 9 6 3 [2,] 14 11 8 5 2 [3,] 13 10 7 4 1 > apply(matrix(15:1, 3), 1, sort) [,1] [,2] [,3] [1,] 3 2 1 [2,] 6 5 4 [3,] 9 8 7 [4,] 12 11 10 [5,] 15 14 13天真的想法应该是这样的:
t(apply(matrix(15:1, 3), 1, sort))但是当在列上进行操作时是不需要转置的—天真的想法就是。
如果组成的因子的级别没有出现,tapply将会返回NA答案(或者NULL如果simplify=FALSE):
tapply(9, factor(1, levels=1:2), sum) 1 2 9 NA tapply(9, factor(1, levels=1:2), sum, simplify=FALSE) “1”[1]9 “2” NULL
函数by复制了tapply的行为:
by(9, factor(1, levels=1:2), sum) factor(1, levels = 1:2): 1 [1] 9 ———————————————————— factor(1, levels = 1:2): 2 [1] NA
函数aggregate剔除了空值:
> aggregate(9, list(factor(1, levels=1:2)), sum) Group.1 x 1 1 9你可以通过split和sapply得到正确的答案:
> sapply(split(9, factor(1, levels=1:2)), sum) 1 2 9 0这种方法基于在split中drop=FALSE的默认值。
在矩阵和向量之间进行乘法运算:
xmat %*% yvec或者
yvec %*% xmatR足够聪明地定向向量使其有意义。没有必要将向量强制转换为矩阵。
如果你想将矩阵的每一行与向量的相应元素进行乘法运算,这样做:
xmat * yvec或者
yvec * xmat因为矩阵的元素的顺序被存储在向量的量级。 但是如果你想用矩阵的每一列乘以相应的向量改怎么做?如果你这样做:
xmat * yvecR不会检查yvec的长度是否和xmat的列数是否匹配,并且做你希望的操作。它做了一个你不想要的操作。有几种方法可以的到你想要的:
xmat * rep(yvec, each=nrow(xmat))和
sweep(xmat, 2, yvec, ’*’)函数sweep相当常用—和它交个朋友吧。函数scale()对于相关的问题是有用的。
当对数据框和矩阵进行下表查找时当心逗号的数量。没有逗号的下标是可以完美接受的—这将对象视为它的下一级向量而不是一个二维的对象。对于数据框,它的下一级是列表并且单独下标和数据框的列数相同。对于矩阵,它的下一级是一个长度等于行数是列数倍数的向量。