关于子集赋值,这种语法如何有用?

时间:2011-06-07 15:29:52

标签: r indexing subset

我一直在阅读R语言定义文件。 最近我发现这种语法是子集赋值的快捷方式。例如

> x <- c(1:16)
> x[3:5] <- 13:15
> x
[1]  1  2 13 14 15  6  7  8  9 10 11 12 13 14 15 16

而不是

> x <- c(1:16)
> x[3:5] <- x[13:15]
> x

这可以在

中更加精细
> x[3:5] <- 13:15 + 15
> x
[1]  1  2 28 29 30  6  7  8  9 10 11 12 13 14 15 16
> x[3:5] <- 13:15*15:15
> x
[1]   1   2 195 210 225   6   7   8   9  10  11  12  13  14  15  16

对我而言,这似乎是一个巧妙的伎俩。另一方面,似乎使用它将不可避免地导致无法读取的代码。

有没有人知道使用这种功能的充分理由?

2 个答案:

答案 0 :(得分:1)

如果您反对覆盖原始对象,请尝试以下操作,返回一个新对象并保持x不变:

xnew <- replace(x, 3:5, 13:15*15:15)

答案 1 :(得分:1)

当您只想替换R中对象的某些元素时,子集赋值是非常有用的。

编程时考虑这个例子。我们有S3通用和方法。我们可能想在输出中打印调用

foo <- function(x, ...) {
    UseMethod("foo")
}

foo.default <- function(x, na.rm = TRUE) {
    obj <- list(fitted.values = mean(x, na.rm = na.rm),
                call = match.call())
    class(obj) <- "foo"
    obj
}

print.foo <- function(x, ...) {
    writeLines(strwrap("Call:"))
    print(x$call)
    cat("\n")
    print(fitted(x), ...)
}

看看我们使用它时会发生什么:

R> set.seed(2)
R> foo(runif(10))
Call:
foo.default(x = runif(10))

[1] 0.5496559

如果电话只是foo(x = runif(10)),那就更好了。我们可以使用子集赋值重写我们的默认方法来重新发送匹配的调用:

foo.default <- function(x, na.rm = TRUE) {
    obj <- list(fitted.values = mean(x, na.rm = na.rm),
                call = match.call())
    obj$call[[1]] <- as.name("foo") ## here is the edit
    class(obj) <- "foo"
    obj
}

哪个更好:

R> set.seed(2)
R> foo(runif(10))
Call:
foo(x = runif(10))

[1] 0.5496559

关键是,我不需要知道如何完整地生成适当的匹配调用,我可以使用子集赋值更新调用的一个方面。当你只需要改变对象的一个​​或几个组件而不仅仅是一个技巧时,这是一个真正的好处。