Wat zijn vervangingsfuncties in R?

Ik heb gezocht naar een referentie om meer te weten te komen over vervangende functies in R, maar ik heb er nog geen gevonden. Ik probeer het concept van de vervangende functies in R te begrijpen. Ik heb de onderstaande code, maar ik begrijp het niet:

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

en dan noemen we cutoff met:

cutoff(x) <- 65

Kan iemand uitleggen wat een vervangingsfunctie is in R?


Antwoord 1, autoriteit 100%

Als je belt

cutoff(x) <- 65

je belt in feite

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

De naam van de functie moet tussen aanhalingstekens staan ​​omdat het een syntactisch geldige maar niet-standaard naam is en de parser <-zou interpreteren als de operator en niet als onderdeel van de functienaam als het werden niet geciteerd.

"cutoff<-"()is net als elke andere functie (zij het met een rare naam); het brengt een wijziging aan in het invoerargument op basis van value(in dit geval stelt het elke waarde in xgroter dan 65in op Inf(oneindig)).

De magie wordt pas echt gedaan als je de functie op deze manier aanroept

cutoff(x) <- 65

omdat R dat aan het ontleden is en de verschillende bits eruit haalt om de hierboven getoonde echte oproep te maken.

Meer algemeen hebben we

FUN(obj) <- value

R vindt functie "FUN<-"()en zet de aanroep op door objen valuedoor te geven aan "FUN<-"()enzorgt ervoor dat het resultaat van "FUN<-"()terug wordt toegewezen aan obj, daarom roept het:

obj <- "FUN<-"(obj, value)

Een nuttige referentie voor deze informatie is de R-taal Definitie Paragraaf 3.4.4: Subset-toewijzing ; de discussie is een beetje scheef, maar lijkt de meest officiële referentie die er is (vervangende functies worden terloops genoemd in de R FAQ (verschillen tussen R en S-PLUS), en in de R taalreferentie (verschillende technische problemen), maar ik heb geen verdere discussie gevonden in de officiële documentatie).


Antwoord 2, autoriteit 19%

Gavin geeft een uitstekende bespreking van de interpretatie van de vervangingsfunctie. Ik wilde een referentie geven omdat je daar ook om vroeg: R Taal DefinitieSectie 3.4.4: Subset-toewijzing.


Antwoord 3, autoriteit 13%

Als aanvulling op het geaccepteerde antwoord zou ik willen opmerken dat vervangende functies ook kunnen worden gedefinieerd voor niet-standaard functies, namelijk operators (zie ?Syntax) en besturingsstroomconstructies. (zie ?Control).

Merk ook op dat het volkomen acceptabel is om generieke en bijbehorende methoden voor vervangende functies te ontwerpen.

operators

Bij het definiëren van een nieuwe klasse is het gebruikelijk om S3-methoden te definiëren voor $<-, [[<-en [<-, enkele voorbeelden zijn data.table:::`$<-.data.table`, data.table:::`[<-.data.table`, of tibble:::`$.tbl_df`.

Voor elke andere operator kunnen we echter een vervangende functie schrijven, enkele voorbeelden:

`!<-` <- 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"

we kunnen zelfs <-<-definiëren, maar de parser zal het gebruik ervan voorkomen als we x <- y <- zaanroepen, dus we moet het toewijzingssymbool van links naar rechts gebruiken

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

Leuk weetje, <<-kan een dubbele rol hebben

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"

controlestroomconstructies

Deze komen in de praktijk zelden voor (in feite ben ik verantwoordelijk voor het enige praktische gebruik dat ik ken, bij het definiëren van for<-voor mijn pakket pbfor), maar R is flexibel genoeg, of gek genoeg, om ons in staat te stellen ze te definiëren . Om ze echter daadwerkelijk te gebruiken, moeten we vanwege de manier waarop besturingsstroomconstructies worden geparseerd, de toewijzing van links naar rechts gebruiken ->.

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

function<-

function<-kan in principe worden gedefinieerd, maar voor zover ik weet kunnen we er niets mee.

`function<-` <- function(x,value){NULL}
3 -> function(arg) {}
#> Error in function(arg) {: target of assignment expands to non-language object

Antwoord 4, autoriteit 6%

Denk eraan, in R is alles een functieaanroep (dus ook de toewijzingsbewerkingen) en is alles wat bestaat een object.
Vervangingsfuncties werken alsof ze hun argumenten op hun plaats wijzigen, zoals in

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

Ze hebben de identifier <-aan het einde van hun naam en retourneren een gewijzigde kopie van het argumentobject (niet-primitieve vervangingsfuncties) of hetzelfde object (primitieve vervangingsfuncties)

Bij de R-prompt werkt het volgende niet:

> `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<-"

Zoals je kunt zien, zoekt R in de omgeving niet naar secondmaar naar second<-.
Dus laten we hetzelfde doen, maar in plaats daarvan zo’n functie-ID gebruiken:

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

Nu werkt de opdracht op de tweede positie van de vector:

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

Ik heb ook een eenvoudig script geschreven om alle vervangende functies in het R-basispakket op te sommen, vind het hier.

Other episodes