Programmer en R/Programmer une fonction
Fonctions définies par l'utilisateur
[modifier | modifier le wikicode]Le logiciel R dispose de fonctions préprogrammées, appelées « primitives ». L'utilisateur a la possibilité de définir ses propres fonctions.
Une fonction est un sous-programme, c'est-à-dire une portion de code qui est exécutée lorsqu'on l'appelle.
Le logiciel R crée un environnement spécifique pour l'exécution de la fonction, c'est-à-dire qu'il travaille avec des variables locales. Ainsi, une variable définie dans une fonction peut avoir le même nom qu'une variable générale, ce sont deux variables indépendantes ; on peut modifier la valeur de cette variable, mais elle retrouve sa valeur initiale lorsque l'on sort de la fonction.
Définition d'une fonction
[modifier | modifier le wikicode]Une fonction est mise dans une variable contenant un bloc d'instructions introduit par la commande function()
. La syntaxe générale est :
nom_de_fonction <- function(arguments) {
instructions
}
par exemple
> carre <- function(x) x*x
> carre(2)
[1] 4
L'évaluation de la fonction renvoie la dernière valeur calculée. On peut préciser la valeur retournée par la commande return()
:
nom_de_fonction <- function(arguments) {
instructions
return(valeur)
}
par exemple
carre <- function(x) {
y <- x*x
return(y)
}
Fonctions sur les vecteurs
[modifier | modifier le wikicode]Les fonctions mathématiques primitives de R s'appliquent sur des vecteurs. On s'attachera donc à créer des fonctions qui s'appliquent elles-mêmes à des vecteurs. Par exemple, la fonction suivante permet de définir une courbe en cloche dissymétrique, formée de deux demies gaussiennes de largeur différentes.
gauss_dissym <- function(A, x) {
# génère un pic gaussien dissymétrique
# entrées : A : vecteur de réels, paramètres de la fonction
# A[1] : position du pic
# A[2] : hauteur de la courbe
# A[3] : largeur de la courbe à gauche
# A[4] : largeur de la courbe à droite
# x : vecteur de réels
# sorties : y : vecteur de réels
indice <- (x < A[1]) # vecteur de T à gauche, F à droite
y <- rep(0, length(x)) # initialisation par des zéros
y[indice] <- A[2]*exp(-(x[indice] - A[1])^2/A[3]) # profil gauche
y[!indice] <- A[2]*exp(-(x[!indice] - A[1])^2/A[4]) # profil droit
return(y)
}
Le fait d'utiliser la matrice de booléens indice permet, au sein d'une seule fonction, de séparer les cas x < A[1] et x ≥ A[1]. On peut donc utiliser cette fonction sur un vecteur :
x <- seq(-5, 5, len=100)
A <- c(1, 1, 2, 5)
y <- gauss_dissym(A , x)
plot(x, y, "l")
Si l'on n'arrive pas à faire autrement, on peut toujours faire défiler les indices avec une boucle, mais l'évaluation de la fonction est alors plus lente.
Récursivité
[modifier | modifier le wikicode]Le langage S est un langage récursif. Une fonction définie dans un script R peut donc s'appeler elle-même, avec la précaution d'usage : il faut prévoir une condition d'arrêt. Comme dans tous les langages récursifs, R crée un environnement spécifique pour l'exécution de la fonction (variables locales), il « empile » les différents appels, puis les « dépile » lorsque la condition d'arrêt est atteinte.
Nous illustrons ceci par le codage récursif de la fonction factorielle.
factorielle <- function(n) {
if (n==1) resultat <- 1 # arrêt de la récursion
else resultat <- factorielle(n-1)*n # appel récursif
return(resultat)
}
Mais nous remarquons que cette fonction ne s'applique qu'aux scalaires, en raison de la présence du test if (n == 1)
: la condition if
ne s'applique que sur un scalaire booléen. On peut modifier le code pour le rendre exécutable sur les vecteurs :
factorielle <- function(n) {
indice <- (n == 1)
if (all(indice)) return(n) # arrêt de la récursion
n[!indice] <- n[!indice]*factorielle(n[!indice] - 1) # appel récursif
return(n)
}
Comme souvent, on crée un vecteur de booléens appelé indice. Si toutes les valeurs sont à « 1 », alors on retourne le vecteur lui-même (puisque 1! = 1) ; c'est l'arrêt de la récursion. Sinon, on extraie le sous-vecteur dont les valeurs ne sont pas « 1 », et l'on applique la récursion.
On peut le tester avec par exemple
> x = c(1:5, 1:5)
> print(x)
[1] 1 2 3 4 5 1 2 3 4 5
> factorielle(x)
[1] 1 2 6 24 120 1 2 6 24 120