49 votes

Que sont les fonctions de remplacement en R ?

J'ai cherché une référence pour apprendre les fonctions de remplacement dans R, mais je n'en ai pas encore trouvé. J'essaie de comprendre le concept des fonctions de remplacement dans R. J'ai le code ci-dessous mais je ne le comprends pas :

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

et on suit le cutoff avec :

 cutoff(x) <- 65

Quelqu'un peut-il expliquer ce qu'est une fonction de remplacement en R ?

6 votes

Il s'agit d'un Q parfaitement acceptable pour le SO

2 votes

0 votes

Voir Prolonger R.- John Chambers (2016) : page 73 à 79 du chapitre 5

50voto

Gavin Simpson Points 72349

Lorsque vous appelez

cutoff(x) <- 65

vous appelez en fait

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

Le nom de la fonction doit être cité car il s'agit d'un nom syntaxiquement valide mais non standard et l'analyseur interpréterait <- comme opérateur et non comme partie du nom de la fonction s'il n'était pas cité.

"cutoff<-"() est juste comme n'importe quelle autre fonction (bien qu'avec un nom bizarre) ; elle modifie son argument d'entrée sur la base de la fonction value (dans ce cas, il s'agit de définir toute valeur dans le champ x plus que 65 à Inf (infini)).

La magie s'opère réellement lorsque vous appelez la fonction comme ceci

cutoff(x) <- 65

parce que R analyse cela et extrait les différents éléments pour faire l'appel réel montré ci-dessus.

Plus généralement, nous avons

FUN(obj) <- value

R trouve la fonction "FUN<-"() et prépare l'appel en passant obj et value en "FUN<-"() et fait en sorte que le résultat de "FUN<-"() pour être réaffecté à obj d'où son nom :

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

Une référence utile pour cette information est le Définition du langage R, section 3.4.4 : Assignation de sous-ensembles La discussion est un peu oblique, mais semble être la référence la plus officielle qui existe (les fonctions de remplacement sont mentionnées en passant dans la FAQ R (différences entre R et S-PLUS), et dans la référence du langage R (divers problèmes techniques), mais je n'ai pas trouvé d'autres discussions dans la documentation officielle).

10voto

Brian Diggs Points 22433

Gavin fournit une excellente discussion sur l'interprétation de la fonction de remplacement. Je voulais fournir une référence puisque vous l'avez également demandé : Définition du langage R Section 3.4.4 : Assignation de sous-ensembles .

5 votes

Utile, mais réponse en lien seulement ... Je modifie la réponse de @GavinSimpson pour l'ajouter ...

6voto

Moody_Mudskipper Points 18115

En complément de la réponse acceptée, j'aimerais noter que les fonctions de remplacement peuvent être définies également pour des fonctions non standard, à savoir les opérateurs (cf. ?Syntax ) et des constructions de flux de contrôle. (voir ?Control ).

Notez également qu'il est parfaitement acceptable de concevoir un générique et des méthodes associées pour les fonctions de remplacement.

opérateurs

Lors de la définition d'une nouvelle classe, il est courant de définir des méthodes S3 pour les éléments suivants $<- , [[<- et [<- Voici quelques exemples data.table:::`$<-.data.table` , data.table:::`[<-.data.table` ou tibble:::`$.tbl_df` .

Cependant pour tout autre opérateur nous pouvons écrire une fonction de remplacement, quelques exemples :

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

nous pouvons même définir <-<- mais l'analyseur syntaxique empêchera son utilisation si nous appelons x <- y <- z Nous devons donc utiliser le symbole d'affectation de gauche à droite.

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

Fait amusant, <<- peut avoir un double rôle

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"

les constructions de flux de contrôle

En pratique, on les rencontre rarement (en fait, je suis responsable de la seule utilisation pratique que je connaisse, dans la définition de l for<- pour mon paquet pbfor ), mais R est assez souple, ou assez fou, pour nous permettre de les définir. Cependant, pour les utiliser réellement, en raison de la manière dont les constructions de flux de contrôle sont analysées, nous devons utiliser l'affectation de gauche à droite. -> .

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

function<-

function<- peut être défini en principe mais, à ma connaissance, on ne peut rien en faire.

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

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

3voto

TMOTTM Points 316

Rappelez-vous, en R, toute opération est un appel de fonction (donc aussi les opérations d'affectation) et tout ce qui existe est un objet. Les fonctions de remplacement agissent comme si elles modifiaient leurs arguments en place, comme dans

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

Ils ont l'identifiant <- à la fin de leur nom et renvoient une copie modifiée de l'objet argument (fonctions de remplacement non primitives) ou le même objet (fonctions de remplacement primitives).

À l'invite R, la commande suivante ne fonctionnera pas :

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

Comme vous pouvez le voir, R cherche dans l'environnement non pas pour second mais pour second<- . Faisons donc la même chose mais en utilisant un tel identifiant de fonction à la place :

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

Maintenant, l'affectation à la deuxième position du vecteur fonctionne :

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

J'ai aussi écrit un simple script pour lister toutes les fonctions de remplacement dans le package de base de R, trouvez-le ici .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X