什么是R中的替换功能?

Sam*_*Sam 48 r

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

"cutoff<-" <- function(x, value){
 x[x > value] <- Inf
 x
 }
Run Code Online (Sandbox Code Playgroud)

然后我们用以下方式调用cutoff:

 cutoff(x) <- 65
Run Code Online (Sandbox Code Playgroud)

谁能解释R中的替换功能是什么?

Rei*_*son 49

你打电话的时候

cutoff(x) <- 65
Run Code Online (Sandbox Code Playgroud)

你实际上在打电话

x <- "cutoff<-"(x = x, value = 65)
Run Code Online (Sandbox Code Playgroud)

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

"cutoff<-"()就像任何其他功能一样(尽管有一个奇怪的名字); 它根据value(在这种情况下设置任何x大于65to Inf(无限)的值)对其输入参数进行更改.

当您调用这样的函数时,真正的魔力正在完成

cutoff(x) <- 65
Run Code Online (Sandbox Code Playgroud)

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

我们一般都有

FUN(obj) <- value
Run Code Online (Sandbox Code Playgroud)

ř发现功能"FUN<-"(),并通过将建立呼叫objvalue"FUN<-"() 安排的结果"FUN<-"()被分配回obj,因此,它调用:

obj <- "FUN<-"(obj, value)
Run Code Online (Sandbox Code Playgroud)

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


Bri*_*ggs 10

Gavin对替换函数的解释提供了很好的讨论.我想提供一个参考,因为您还要求:R语言定义第3.4.4节:子集分配.

  • 有用,但仅链接答案...我正在编辑@ GavinSimpson的答案添加它... (5认同)

Moo*_*per 7

作为对已接受答案的补充,我想指出,也可以为非标准函数定义替换函数,即运算符(请参阅 参考资料?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"
Run Code Online (Sandbox Code Playgroud)

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

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

有趣的事实,<<-可以有双重作用

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"
Run Code Online (Sandbox Code Playgroud)

控制流结构

这些在实践中很少遇到(事实上,我负责我所知道的唯一实际用途,for<-为我的包pbfor定义),但 R 足够灵活,或者足够疯狂,允许我们定义它们。然而要实际使用它们,由于控制流构造的解析方式,我们需要使用从左到右的赋值->

`repeat<-` <- function(x, value) replicate(value, x)
x <- "foo"
3 -> repeat x
x
#> [1] "foo" "foo" "foo"
Run Code Online (Sandbox Code Playgroud)

function<-

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

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

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

  • 我无法决定是赞成还是反对这个答案……! (3认同)