8.1 幽灵(no.41~no.50)

    xiaoxiao2025-01-21  10

    8.1 幽灵(no.41~no.50)

    8.1.41 字符串不是名字(IV)

    一个公式可以很容易地由字符串创建:

    > 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

    8.1.42 未命名参数

    你或许想制造一个plot或者其他输出来描述已经使用的数据。你或许这样做:

    myfun <- function(x, ...) { plot(x, main=x, ...) }

    但是这个将会产生一个不那么令人愉快的主题。函数substitute()搭配函数deparse()或许是你所寻找的:

    myfun2 <- function(x, ...) { plot(x, main=deparse(substitute(x)), ...) }

    8.1.43 出乎意料的else

    Error: unexpected ’else’ in "else"

    如果你没有在”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) }

    8.1.44 降位

    > xmat <- array(1:4, c(2,2)) > xmat[1,] # simple vector, not a matrix [1] 1 3 > xmat[1, , drop=FALSE] # still a matrix [,1] [,2] [1,] 1 3

    默认情况下,当下标化为1时,数组的维度将会被降低。使用drop=FALSE的下标化会重载默认情况。

    NOTE: 没有在函数中使用drop=FALSE是错误的主要来源。你仅仅是测试了函数当下标大于1的情况。当下标为1时,函数就不行了—在此地降维一个矩阵是被期望的并且被简单的向量替代。 NOTE: 没有在函数中使用drop=FALSE是错误的主要来源(再次强调)。

    8.1.45 数据框降维

    函数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

    8.1.46 行名丢失

    在降维过程中数据框的行名丢失了:

    > 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

    最后一行代码,尽管有点复杂,但却会给你正确的答案。

    8.1.47 返回一个向量的apply函数

    如果你在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))

    但是当在列上进行操作时是不需要转置的—天真的想法就是。

    8.1.48 tapply遇到空

    如果组成的因子的级别没有出现,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的默认值。

    8.1.49 矩阵和向量之间的乘法

    在矩阵和向量之间进行乘法运算:

    xmat %*% yvec

    或者

    yvec %*% xmat

    R足够聪明地定向向量使其有意义。没有必要将向量强制转换为矩阵。

    如果你想将矩阵的每一行与向量的相应元素进行乘法运算,这样做:

    xmat * yvec

    或者

    yvec * xmat

    因为矩阵的元素的顺序被存储在向量的量级。 但是如果你想用矩阵的每一列乘以相应的向量改怎么做?如果你这样做:

    xmat * yvec

    R不会检查yvec的长度是否和xmat的列数是否匹配,并且做你希望的操作。它做了一个你不想要的操作。有几种方法可以的到你想要的:

    xmat * rep(yvec, each=nrow(xmat))

    sweep(xmat, 2, yvec, ’*’)

    函数sweep相当常用—和它交个朋友吧。函数scale()对于相关的问题是有用的。

    8.1.50 数据框或者数组的单独下标

    当对数据框和矩阵进行下表查找时当心逗号的数量。没有逗号的下标是可以完美接受的—这将对象视为它的下一级向量而不是一个二维的对象。对于数据框,它的下一级是列表并且单独下标和数据框的列数相同。对于矩阵,它的下一级是一个长度等于行数是列数倍数的向量。

    转载请注明原文地址: https://ju.6miu.com/read-1295692.html
    最新回复(0)