什么是R中的替换功能?

时间:2012-07-19 14:35:39

标签: r

我搜索了一个参考,以了解R中的替换函数,但我还没有找到。我试图理解R中替换函数的概念。我有下面的代码,但我不明白:

"cutoff<-" <- function(x, value){
 x[x > value] <- Inf
 x
 }

然后我们用:

调用cutoff
 cutoff(x) <- 65

有人可以解释一下R中的替代功能吗?

4 个答案:

答案 0 :(得分:46)

致电时

cutoff(x) <- 65

你实际上是在打电话

x <- "cutoff<-"(x = x, value = 65)

必须引用函数的名称,因为它是一个语法上有效但非标准的名称,如果没有引用,解析器会将<-解释为操作符而不是函数名称的一部分。

"cutoff<-"()就像任何其他函数一样(尽管有一个奇怪的名字);它基于value对其输入参数进行了更改(在这种情况下,它将x中的任何值设置为大于65Inf(无限))。

当你像这样调用这个函数时,真正的魔力已经完成了

cutoff(x) <- 65

因为R正在解析它并拉出各个位以进行上面显示的真实调用。

通常我们有

FUN(obj) <- value

R找到函数"FUN<-"()并通过将objvalue传递到"FUN<-"() 安排{{1>}的结果来设置调用1}}被分配回"FUN<-"(),因此它调用:

obj

此信息的有用参考是R Language Definition Section 3.4.4: Subset assignment ;讨论有点倾斜,但似乎是最官方的参考(替换函数在R FAQ(R和S-PLUS之间的差异)中提及,并且在R语言参考(各种技术问题)中,但我没有在官方文件中找到任何进一步的讨论。)

答案 1 :(得分:10)

Gavin对替换函数的解释提供了很好的讨论。我想提供一个参考,因为您还要求:R Language Definition Section 3.4.4: Subset assignment

答案 2 :(得分:4)

作为已接受答案的补充,我想指出,替换函数也可以为非标准函数定义,即运算符(请参见?Syntax)和控制流构造。 (请参阅?Control)。

还请注意,为替换函数设计通用和相关方法完全可以接受。

操作员

定义新类时,通常为$<-[[<-[<-定义S3方法,例如data.table:::`$<-.data.table`data.table:::`[<-.data.table`tibble:::`$.tbl_df`

但是,对于其他任何运算符,我们都可以编写替换函数,例如:

`!<-` <- function(x, value) !value
x <- NULL # x needs to exist before replacement functions are used!
!x <- TRUE
x
#> [1] FALSE

`==<-` <- function(e1, e2, value) replace(e1, e1 == e2, value)
x <- 1:3
x == 2 <- 200
x
#> [1]   1 200   3

`(<-` <- function(x, value) sapply(x, value, USE.NAMES = FALSE)
x <- c("foo", "bar")
(x) <- toupper
x 
#> [1] "FOO" "BAR"

`%chrtr%<-` <- function(e1, e2, value) {
  chartr(e2, value, e1)
}

x <- "woot"
x %chrtr% "o" <- "a"
x
#> [1] "waat"

我们甚至可以定义<-<-,但是如果调用x <- y <- z,解析器将阻止使用它,因此我们需要使用从左到右的赋值符号

`<-<-` <- function(e1, e2, value){
  paste(e2, e1, value)
}
x <- "b"
"a" -> x <- "c"
x
#> [1] "a b c"

有趣的是,<<-可以扮演双重角色

x <- 1:3
x < 2 <- NA # this fails but `<<-` was called!
#> Error in x < 2 <- NA: incorrect number of arguments to "<<-"

# ok let's define it then!
`<<-` <- function(x, y, value){
  if (missing(value)) {
    eval.parent(substitute(.Primitive("<<-")(x, y)))
  } else {
    replace(x, x < y, value)
  }
}
x < 2 <- NA
x
#> [1] NA  2  3
x <<- "still works"
x
#> [1] "still works"

控制流构造

这些在实践中很少遇到(实际上,我负责为我的软件包pbfor定义for<-的唯一实际用途),但是R足够灵活,或者足够疯狂,以便我们对其进行定义。但是,要实际使用它们,由于解析控制流构造的方式,我们需要使用从左到右的赋值->

`repeat<-` <- function(x, value) replicate(value, x)
x <- "foo"
3 -> repeat x
x
#> [1] "foo" "foo" "foo"

function<-

function<-可以原则上定义,但就我所知,我们对此无能为力。

`function<-` <- function(x,value){NULL}

3 -> function(arg) {}
#> Error in function(arg) {: target of assignment expands to non-language object

答案 3 :(得分:2)

请记住,在R中,所有操作都是函数调用(因此也是赋值操作),并且存在的所有内容都是对象。 替换函数就好像它们修改了它们的参数一样,例如在

colnames(d) <- c("Input", "Output")

他们的名字末尾有标识<-,并返回参数对象的修改副本(非原始替换函数)或同一对象(原始替换函数)

在R提示符下,以下内容无效:

> `second` <- function(x, value) {
+   x[2] <- value
+   x
+ }
> x <- 1:10
> x
 [1]  1  2  3  4  5  6  7  8  9 10
> second(x) <- 9
Error in second(x) <- 9: couldn't find function "second<-"

如您所见,R正在搜索环境,不是second而是second<-。 所以让我们做同样的事情,但改为使用这样的函数标识符:

> `second<-` <- function(x, value) {
+   x[2] <- value
+   x
+ }

现在,向量的第二个位置的赋值有效:

> second(x) <- 9
> x
 [1]  1  9  3  4  5  6  7  8  9 10

我还写了一个简单的脚本来列出R base包中的所有替换函数find it here