我一直在阅读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
对我而言,这似乎是一个巧妙的伎俩。另一方面,似乎使用它将不可避免地导致无法读取的代码。
有没有人知道使用这种功能的充分理由?
答案 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
关键是,我不需要知道如何完整地生成适当的匹配调用,我可以使用子集赋值更新调用的一个方面。当你只需要改变对象的一个或几个组件而不仅仅是一个技巧时,这是一个真正的好处。