Fonctions

Les blocs entre parenthèses
Avant de passer aux fonctions, nous avons besoin de préciser quelques points sur les expressions. Les
expressions sont evaluées pour créer des objets. Elles sont constituées d.opérateurs (+, *, ^) et d.autres
objets (variables ou constantes) par exemple :
2 + 2, sin(x)^2.
a <- 2 + 2
a
[1] 4
b <- sin(a)^2
b
[1] 0.57275
Expression et objets : blocs
a des blocs d.expressions qui sont une suite d.expressions encadrées par des accolades. Toutes les expres-
sions d.un bloc sont evaluées les unes a la suite des autres. Tous les assignements de variables seront e¤ectifs
et tous les appels a
print() ou plot() auront les e¤ets collat attendus. Mais le plus important est que le bloc entier est lui-eme
une expression dont la valeur sera la derniere expression evaluée dans le bloc.
monbloc <- {
tmp <- 1:10
somme <- sum(tmp)
}
tmp
[1] 1 2 3 4 5 6 7 8 9 10
somme
2
[1] 55
monbloc
[1] 55
Dé?nition de la fonction :
hello <- function() {
print("Hello world")
}
Appel de la fonction :
hello()
[1] "Hello world"
Une fonction qui retourne ses arguments
mafonction <- function(a = 1, b = 2, c) {
resultat <- c(a, b, c)
names(resultat) <- c("a", "b", "c")
return(resultat)
}
mafonction(6, 7, 8)
a b c
6 7 8
1
mafonction(10, c = "bien")
a b c
"10" "2" "bien"
Pour une fonction donnée, la liste de ses arguments (avec les valeurs par défaut eventuelles) est donnée
par la fonction args() :
args(mafonction)
function (a = 1, b = 2, c)
NULL
Pour une fonction donnée, le corps de la fonction est donnée par la fonction body :
body(mafonction)
{
resultat <- c(a, b, c)
names(resultat) <- c("a", "b", "c")
return(resultat)
}
On peut aussi entrer le nom de la fonction sans les parenthéses pour avoir args()+body() :
mafonction
function (a = 1, b = 2, c)
{
resultat <- c(a, b, c)
names(resultat) <- c("a", "b", "c")
return(resultat)
}
Illustration de la portée des variable
mavariable <- 1
mafonction1 <- function() {
mavariable <- 5
print(mavariable)
}
mafonction1()
[1] 5
mavariable
[1] 1
mafonction2 <- function() {
print(mavariable)
}
mafonction2()
[1] 1
cube <- functionNon {
carre <- function() n * n
n * carre()
}
cube(2)


















    Structures de controle

                         Faire des choix
    if(cond) expr
    Pour faire un choix simple :
    f <- function(x) {
    if (x%%2 == 0) {
    return("pair")
    }
    }
    f(2)
    
    if(cond) expr1 else expr2
    Pour faire choisir entre une condition et son alternative :
    f <- function(x) {
    if (x%%2 == 0) {
    return("pair")
    }
    else {
    return("impair")
    }
    }
    f(2)
    [1] "pair"
    f(3)
    [1] "impair"
    [1] "pair"
    f(3)
    
    while.   Tant que la condition est vraie on répéte l'expression :
    i <- 1
    while (i <= 5) {
    print(i)
    i <- i + 1
    }
    [1] 1
    [1] 2
    [1] 3
    [1] 4
    
    switch(expr, ...).  Pour faire des choix multiples :
    f <- function(x) {
    switch(x, "un", "deux", "trois", "quatre")
    }
    f(1)
    [1] "un"
    f(2)
    [1] "deux"
    f(5)
    NULL
    [1] 5
    
    switch(expr, )   En travaillant avec une expression de type chaine de caractères on peut préciser un choix par défaut :
    f <- function(chaine) {
    switch(chaine, un = 1, deux = 2, trois = 3, quatre = 4,
    "je ne sais pas")
    }
    f("un")
    [1] 1
    f("deux")
    [1] 2
    f("cent")
    [1] "je ne sais pas"
    
    ifelse(test, oui, non)
    Il existe une version vectorisée trés puissante :
    x <- rnorm(10)
    x
    [1] -0.47162735 -0.77978020 -1.07174132 -1.29467154 -0.47645939
    [6] 0.52778427 0.49125277 -1.59025716 -2.74457419 -0.03007822
    ifelse(x > 0, "positif", "negatif")
    [1] "negatif" "negatif" "negatif" "negatif" "negatif" "positif"
    [7] "positif" "negatif" "negatif" "negatif"
    
    Repeter une action
    
    On est souvent amené a faire des simulations pour apprécier la distribution d'échantillonnage d'une statistique. La fonction
    replicate() permet de le faire trés facilement :
    hist(replicate(500, mean(rnorm(100))), col = "lightblue")
    
    for(var in seq) expr
    On peut aussi faire des boucles explicites a l'ancienne :
    for (i in 1:5) print(i)
    [1] 1
    [1] 2
    [1] 3
    [1] 4
    [1] 5
    for (carac in letters[1:5]) print(carac)
    [1] "a"
    [1] "b"
    [1] "c"
    [1] "d"
    [1] "e"
    
for(var in seq) expr
    Remplacer toutes les valeurs négatives d'un vecteur par -1.
    Approche laborieuse classique :
    x <- rnorm(10)
    for (i in 1:length(x)) {
    if (x[i] < 0)
    x[i] <- -1
    }x
    [1] -1.00000000 0.57698909 0.52651301 -1.00000000 1.06504920
    [6] 0.00999927 -1.00000000 0.71572971 -1.00000000 -1.00000000
    Approche sous :
    x <- rnorm(10)
    x[x < 0] <- -1
    x
    [1] 0.99210114 0.81975449 2.21701969 1.46007751 0.01846901
    [6] -1.00000000 -1.00000000 0.11346376 -1.00000000 -1.00000000
    
    Remarque : on aurait pu utiliser aussi ici le if vectorisé ainsi :
    x <- rnorm(10)
    x <- ifelse(x < 0, -1, x)
    x
    [1] -1.0000000 1.3615624 1.5683767 1.1430187 -1.0000000 -1.0000000
    [7] 0.4646724 1.1394565 -1.0000000 -1.0000000
    
    while(cond) expr
    Tant que la condition est vraie on répéte l'expression :
    i <- 1
    while (i <= 5) {
    print(i)
    i <- i + 1
    }
    [1] 1
    [1] 2
    [1] 3
    [1] 4
    [1] 5
    
repeat expr
    On répéte l'expression tant qu'un break n'en fait pas sortir :
    i <- 1
    repeat {
    print(i)
    i <- i + 1
    if (i > 5)
    break
    }
    [1] 1
    [1] 2
    [1] 3
    [1] 4
    [1] 5
    
    next
    On peut sauter un tour dans une boucle. Par exemple pour mettre
     a zéro tous leséléments d'une matrice sauf leséléments
    diagonaux :
    (x <- matrix(rnorm(9), 3, 3))
    [,1] [,2] [,3]
    [1,] 1.2478061 0.06974192 -0.1352661
    [2,] 1.6225568 0.64071224 -0.5948983
    [3,] 0.5394343 1.68095070 1.0463645
    for (i in 1:3) {
    for (j in 1:3) {
    if (i == j)
    next
    x[i, j] <- 0
    }
    }x
    [,1] [,2] [,3]
    [1,] 1.247806 0.0000000 0.000000
    [2,] 0.000000 0.6407122 0.000000
    [3,] 0.000000 0.0000000 1.046365
    
    
Remarque : sous , on ferait plus simplement :
    (x <- matrix(rnorm(9), 3, 3))
    [,1] [,2] [,3]
    [1,] 1.146043 -0.2329530 -0.1141616
    [2,] 1.040547 -1.6224200 1.9552784
    [3,] 0.954766 -0.8191705 -1.0065945
    (x <- diag(diag(x)))
    [,1] [,2] [,3]
    [1,] 1.146043 0.00000 0.000000
    [2,] 0.000000 -1.62242 0.000000
    [3,] 0.000000 0.00000 -1.006594
    
    Boucles implicites
    lapply()
    lapply() permet d'appliquer une fonction a tous leséléments
    d'une liste ou d'un vecteur :
    maliste <- as.list(1:3)
    f <- function(x) x^2
    lapply(maliste, f)
    [[1]]
    [1] 1
    [[2]]
    [1] 4
    [[3]]
    [1] 9
    
    lapply() retourne une liste :
    lapply(1:4, f)
    [[1]]
    [1] 1
    [[2]]
    [1] 4
    [[3]]
    [1] 9
    [[4]]
    [1] 16
    
    sapply()
    sapply() essaye de simpli er le résultat en un vecteur :
    sapply(maliste, f)
    [1] 1 4 9
    sapply(1:10, f)
    [1] 1 4 9 16 25 36 49 64 81 100
    
    tapply()
    La fonction tapply() permet d'appliquer une fonction a des groupes
    dé nis par une variable qualitative :
    data(iris)
    head(iris)
    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
    1 5.1 3.5 1.4 0.2 setosa
    2 4.9 3.0 1.4 0.2 setosa
    3 4.7 3.2 1.3 0.2 setosa
    4 4.6 3.1 1.5 0.2 setosa
    5 5.0 3.6 1.4 0.2 setosa
    6 5.4 3.9 1.7 0.4 setosa
    tapply(iris$Sepal.Length, iris$Species, mean)
    setosa versicolor virginica
    5.006 5.936 6.588
    
    
apply()
    apply() permet d'appliquer une fonction aux lignes (1) ou aux
    colonnes (2) d'une matrice :
    (mat <- matrix(rpois(12, 2), 3, 4))
    [,1] [,2] [,3] [,4]
    [1,] 1 2 3 3
    [2,] 3 3 3 1
    [3,] 0 1 2 2
    apply(mat, 1, sum)
    [1] 9 10 5
    apply(mat, 2, sum)
    [1] 4 6 8 6
    
    Remarque : les fonctions colSums() et rowSums() permettent
    d'obtenir le m^eme r esultat :
    rowSums(mat)
    [1] 9 10 5
    colSums(mat)
    [1] 4 6 8 6
    
    Exemple d'application : on considére le jeu de données airquality :
    data(airquality)
    head(airquality)
    Ozone Solar.R Wind Temp Month Day
    1 41 190 7.4 67 5 1
    2 36 118 8.0 72 5 2
    3 12 149 12.6 74 5 3
    4 18 313 11.5 62 5 4
    5 NA NA 14.3 56 5 5
    6 28 NA 14.9 66 5 6
    Il y a des données manquantes. Que faire ?
    
    Premiere solution : ne garder que les individus entierement documentés :
    head(airquality)
    Ozone Solar.R Wind Temp Month Day
    1 41 190 7.4 67 5 1
    2 36 118 8.0 72 5 2
    3 12 149 12.6 74 5 3
    4 18 313 11.5 62 5 4
    5 NA NA 14.3 56 5 5
    6 28 NA 14.9 66 5 6
    head(airquality[complete.cases(airquality), ])
    Ozone Solar.R Wind Temp Month Day
    1 41 190 7.4 67 5 1
    2 36 118 8.0 72 5 2
    3 12 149 12.6 74 5 3
    4 18 313 11.5 62 5 4
    7 23 299 8.6 65 5 7
    8 19 99 13.8 59 5 8
    
    Deuxi eme solution : remplacer les valeurs manquantes par la
    moyenne de la variable. Approche a l'ancienne :
    for (i in 1:nrow(airquality)) {
    for (j in 1:ncol(airquality)) {
    if (is.na(airquality[i, j])) {
    airquality[i, j] <- mean(airquality[, j],
    na.rm = TRUE)
    }
    }
    }
    head(airquality)
    Ozone Solar.R Wind Temp Month Day
    1 41.00000 190.0000 7.4 67 5 1
    2 36.00000 118.0000 8.0 72 5 2
    3 12.00000 149.0000 12.6 74 5 3
    4 18.00000 313.0000 11.5 62 5 4
    5 42.12931 185.9315 14.3 56 5 5
    6 28.00000 185.9315 14.9 66 5 6
    
    Approche avec apply() :
    data(airquality)
    head(apply(airquality, 2, function(x) ifelse(is.na(x),
    mean(x, na.rm = TRUE), x)))
    Ozone Solar.R Wind Temp Month Day
    [1,] 41.00000 190.0000 7.4 67 5 1
    [2,] 36.00000 118.0000 8.0 72 5 2
    [3,] 12.00000 149.0000 12.6 74 5 3
    [4,] 18.00000 313.0000 11.5 62 5 4
    [5,] 42.12931 185.9315 14.3 56 5 5
    [6,] 28.00000 185.9315 14.9 66 5 6








Modifié le: mercredi 29 juin 2022, 00:35