Lorsque je demande à R de stocker en mémoire le nombre 1.14, quel nombre garde-t-il en mémoire réellement ?
Lorsque je demande à R de stocker en mémoire le nombre 10000000000000001, quel nombre garde-t-il en mémoire réellement ?
# Sur mon ordinateur, j'obtiens
# Afin d'éviter l'affichage en notation scientifique
options_default <- options() # copie des options par défaut conservée
options(scipen = 12)
# Affichage du nombre
print(10000000000000001)
## [1] 10000000000000000
# Pour remettre les options par défaut
options(options_default)Supposons que nous chargeons en R le package jsonlite
avec la commande :
library(jsonlite)
Ensuite, nous chargeons le package rjson avec la
commande :
library(rjson)
Maintenant, nous voulons utiliser la fonction fromJSON
du package jsonlite. Comment faire ?
library(jsonlite)
library(rjson)
# Comment utiliser la fonction fromJSON du package jsonlite ?
fromJSON # pas la bonne fonction car rjson a été chargé après jsonlite
# Solution : utiliser l'opérateur ::
jsonlite::fromJSON
# ou détacher le package rjson du chemin de recherche
detach(package:rjson)
fromJSONÉcrivez un bout de code R qui dépend d’un objet nommé
message.
message contient uniquement la chaîne de caractères
"Bonjour", le code doit provoquer l’impression de
message.message contient plutôt la chaîne de caractères
"Au revoir", le code doit modifier message
afin qu’il prenne plutôt la valeur "À la prochaine".message contient n’importe quoi d’autre, le code
doit créer un nouvel objet nommé reponse, contenant la
valeur "Quoi?" et imprimer cet objet.Trouvez deux solutions :
if … else,switch.message <- "Bonjour" # pour expérimenter
# Solution avec if ... else
if (isTRUE(message == "Bonjour")) {
print(message)
} else if (isTRUE(message == "Au revoir")) {
message <- "À la prochaine"
} else {
reponse <- "Quoi?"
print(reponse)
}
# Solution avec switch
switch(
message,
"Bonjour" = {
print(message)
},
"Au revoir" = {
message <- "À la prochaine"
},
{
reponse <- "Quoi?"
print(reponse)
}
)Cet exercice utilise le jeu de données airquality du
package datasets.
Écrivez une boucle qui produit un résultat équivalent à celui de la commande suivante :
apply(airquality, MARGIN = 2, FUN = range, na.rm = TRUE)
## Ozone Solar.R Wind Temp Month Day
## [1,] 1 7 1.7 56 5 1
## [2,] 168 334 20.7 97 9 31
NOTE : Cet exercice permet de pratiquer l’écriture d’une boucle
for, mais l’utilisation de la fonction apply
est recommandée pour faire ce calcul.
# À reproduire :
out_1_ref <- apply(airquality, MARGIN = 2, FUN = range, na.rm = TRUE)
out_1_ref
## Ozone Solar.R Wind Temp Month Day
## [1,] 1 7 1.7 56 5 1
## [2,] 168 334 20.7 97 9 31
str(out_1_ref)
## num [1:2, 1:6] 1 168 7 334 1.7 20.7 56 97 5 9 ...
## - attr(*, "dimnames")=List of 2
## ..$ : NULL
## ..$ : chr [1:6] "Ozone" "Solar.R" "Wind" "Temp" ...
# Initialisation d'un objet pour contenir les résultats :
out_1 <- matrix(NA, nrow = 2, ncol = ncol(airquality))
colnames(out_1) <- names(airquality)
# Boucle :
for (col in names(airquality)) {
out_1[, col] <- range(airquality[, col], na.rm = TRUE)
}
# J'aurais aussi pu itérer sur les positions 1 à ncol(airquality).
out_1
## Ozone Solar.R Wind Temp Month Day
## [1,] 1 7 1.7 56 5 1
## [2,] 168 334 20.7 97 9 31
all.equal(out_1, out_1_ref)
## TRUECet exercice utilise aussi le jeu de données airquality
du package datasets.
Écrivez une boucle qui produit un résultat équivalent à celui de la commande suivante :
aggregate(Temp ~ Month, data = airquality, FUN = mean)
NOTE : Cet exercice permet de pratiquer l’écriture d’une boucle
for, mais l’utilisation de la fonction
aggregate, ou d’une autre outil qui permet d’éviter la
boucle, est recommandée pour faire ce calcul.
# À reproduire :
out_2_ref <- aggregate(Temp ~ Month, data = airquality, FUN = mean)
out_2_ref
## Month Temp
## 1 5 65.54839
## 2 6 79.10000
## 3 7 83.90323
## 4 8 83.96774
## 5 9 76.90000
str(out_2_ref)
## 'data.frame': 5 obs. of 2 variables:
## $ Month: int 5 6 7 8 9
## $ Temp : num 65.5 79.1 83.9 84 76.9
# Initialisation d'un objet pour contenir les résultats :
out_2 <- data.frame(Month = unique(airquality$Month), Temp = NA)
# Boucle :
for (i in seq_len(nrow(out_2))) {
out_2$Temp[i] <- mean(subset(
airquality,
subset = Month == out_2$Month[i],
select = Temp,
drop = TRUE
))
}
out_2
## Month Temp
## 1 5 65.54839
## 2 6 79.10000
## 3 7 83.90323
## 4 8 83.96774
## 5 9 76.90000
all.equal(out_2, out_2_ref)
## TRUECet exercice utilise le facteur state.division du
package datasets.
Soumettez les commandes suivantes dans la console :
ma_liste <- strsplit(levels(state.division), split = " ")
names(ma_liste) <- paste0("division", seq_along(ma_liste))
L’objet ma_liste est une liste dont les 9 éléments sont
des vecteurs de différentes longueurs. Écrivez une boucle qui extrait le
dernier élément de chaque vecteur et qui retourne un resultat formaté
comme celui de la commande suivante.
sapply(ma_liste, FUN = tail, n = 1)
## division1 division2 division3 division4 division5 division6 division7 division8 division9
## "England" "Atlantic" "Atlantic" "Central" "Central" "Central" "Central" "Mountain" "Pacific"
CONTRAINTE : La boucle doit itérer sur les entiers 1 à
9 en référence aux positions des éléments de
ma_liste.
NOTE : Encore une fois, cet exercice permet de pratiquer l’écriture
d’une boucle for, mais l’utilisation de la fonction
sapply (ou une autre fonction de la famille des
apply) est recommandée pour faire ce calcul.
# À reproduire :
ma_liste <- strsplit(levels(state.division), split = " ")
names(ma_liste) <- paste0("division", seq_along(ma_liste))
sapply(ma_liste, FUN = tail, n = 1)
## division1 division2 division3 division4 division5 division6 division7 division8 division9
## "England" "Atlantic" "Atlantic" "Central" "Central" "Central" "Central" "Mountain" "Pacific"
# Initialisation d'un objet pour contenir les résultats :
boucle_1 <- vector(mode = "character", length = length(ma_liste))
names(boucle_1) <- names(ma_liste)
# Boucle :
for (i in seq_along(ma_liste)) {
boucle_1[i] <- tail(ma_liste[[i]], n = 1) # ou ma_liste[[i]][length(ma_liste[[i]])]
}
boucle_1
## division1 division2 division3 division4 division5 division6 division7 division8 division9
## "England" "Atlantic" "Atlantic" "Central" "Central" "Central" "Central" "Mountain" "Pacific" Réécrivez la boucle précédente, cette fois en itérant sur les
noms des éléments de ma_liste.
# Initialisation d'un objet pour contenir les résultats :
boucle_2 <- vector(mode = "character", length = length(ma_liste))
names(boucle_2) <- names(ma_liste)
# Boucle :
for (nom in names(ma_liste)) {
boucle_2[nom] <- tail(ma_liste[[nom]], n = 1)
}
boucle_2
## division1 division2 division3 division4 division5 division6 division7 division8 division9
## "England" "Atlantic" "Atlantic" "Central" "Central" "Central" "Central" "Mountain" "Pacific" Réécrivez encore une fois la boucle précédente, cette fois en
itérant directement sur les éléments de la liste
ma_liste.
# Initialisation d'un objet pour contenir les résultats :
boucle_3 <- vector(mode = "character", length = length(ma_liste))
names(boucle_3) <- names(ma_liste)
# Boucle :
i <- 0
for (element in ma_liste) {
i <- i + 1
boucle_3[i] <- tail(element, n = 1)
}
boucle_3
## division1 division2 division3 division4 division5 division6 division7 division8 division9
## "England" "Atlantic" "Atlantic" "Central" "Central" "Central" "Central" "Mountain" "Pacific" Résolvez maintenant le problème d’extraire le dernier élément de
chaque vecteur dans la liste ma_liste par un appel à la
fonction sapply, qui fait lui appel à une fonction anonyme
que vous devez écrire.
sapply(ma_liste, FUN = function(x) tail(x, n = 1))
# ou
sapply(ma_liste, FUN = function(x) x[length(x)])
## division1 division2 division3 division4 division5 division6 division7 division8 division9
## "England" "Atlantic" "Atlantic" "Central" "Central" "Central" "Central" "Mountain" "Pacific"
# Remarque :
# Une autre solution possible (qui n'utilise cependant pas de fonction anonyme) :
mapply(FUN = "[", ma_liste, lapply(ma_liste, FUN = length))Écrivez une fonction R qui prend un entrée un vecteur numérique et
qui retourne en sortie la position du premier nombre entier impair dans
ce vecteur. La fonction doit retourner NA si le vecteur ne
contient aucun nombre impair.
EXEMPLE :
x <- c(6, 3, 5.5, 1, 0, -5)
pos_1er_impair(x)
## [1] 2
CONTRAINTE : Votre fonction doit parcourir le vecteur donné en entrée jusqu’au premier nombre impair seulement. Ainsi, elle parcourt tout le vecteur uniquement si le premier nombre impair se trouve à la dernière position ou si le vecteur ne comporte aucun nombre impair.
INDICE : Une boucle while ou repeat vous
sera utile.
# Fonction qui retourne la position du premier nombre
# entier impair dans un vecteur numérique
# Argument en entrée : x = vecteur numérique
# Sortie : la position du 1er entier impair dans x
pos_1er_impair <- function(x) {
pos <- NA
i <- 0
while (is.na(pos) && i < length(x)) {
i <- i + 1
# cat("Vérification de la position", i, "\n")
if (!is.na(x[i]) && x[i] %% 2 == 1) {
pos <- i
}
}
return(pos)
}
# Pour tester un peu la fonction
pos_1er_impair(c(6, 3, 5.5, 1, 0, -5))
## [1] 2
pos_1er_impair(c(6, 4, 5.5, 2, 0, -5))
## [1] 6
pos_1er_impair(c(6, 2, 5.5))
## [1] NAReprenez la fonction compte_impair_vectoriel des notes
de cours et ajoutez-lui un argument na.rm, prenant comme
valeur par défaut FALSE, qui traite les valeurs manquantes
de la même façon que l’argument na.rm de la fonction
range (et de plusieurs autres fonctions).
compte_impair_vectoriel <- function(x) {
sum(x %% 2 == 1)
}
Reprenez la fonction compte_impair_boucle des notes de
cours et ajoutez-lui un argument na.rm, prenant comme
valeur par défaut FALSE, comme vous venez de le faire pour
la fonction compte_impair_vectoriel.
compte_impair_boucle <- function(x) {
k <- 0
for (n in x) {
if (n %% 2 == 1) k <- k + 1
}
k
}
compte_impair_boucle <- function(x, na.rm = FALSE) {
k <- 0
for (n in x) {
if (is.na(n)) {
if (na.rm) {
next
} else {
k <- NA
break
}
} else {
if (n %% 2 == 1) k <- k + 1
}
}
k
}
# Autre approche :
# retirer les NA si na.rm prend la valeur TRUE
compte_impair_boucle <- function(x, na.rm = FALSE) {
if (na.rm) x <- na.omit(x)
if (any(is.na(x))) {
k <- NA
} else {
k <- 0
for (n in x) {
if (n %% 2 == 1) k <- k + 1
}
}
k
}
compte_impair_boucle(c(6, 3, 5.5, NA, 0, -5))
## [1] NA
compte_impair_boucle(c(6, 3, 5.5, NA, 0, -5), na.rm = TRUE)
## [1] 2Créez une nouvelle fonction, nommée compte_impair, qui a
la même utilité que les fonctions compte_impair_vectoriel
et compte_impair_boucle.
Cette fonction doit posséder, en plus des arguments x et
na.rm comme ceux de compte_impair_vectoriel et
compte_impair_boucle, un nouvel argument servant à
contrôler la façon dont la fonction effectue le calcul. Ce nouvel
argument doit être nommé methode et doit accepter seulement
deux valeurs : "calcul_vectoriel" (la valeur par défaut) ou
"boucle".
Si methode prend la valeur
"calcul_vectoriel", compte_impair doit appeler
la fonction compte_impair_vectoriel pour faire le calcul.
Si methode prend plutôt la valeur "boucle",
compte_impair doit appeler la fonction
compte_impair_boucle.
La nouvelle fonction doit seulement retourner ce que l’appel à la
fonction compte_impair_vectoriel ou
compte_impair_boucle retourne.
compte_impair <- function(x, na.rm = FALSE, methode = c("calcul_vectoriel", "boucle")) {
methode <- match.arg(methode)
if (methode == "calcul_vectoriel") {
print("Calcul vectoriel effectué")
compte_impair_vectoriel(x = x, na.rm = na.rm)
} else if (methode == "boucle") {
print("Boucle effectuée")
compte_impair_boucle(x = x, na.rm = na.rm)
}
}
compte_impair(c(6, 3, 5.5, NA, 0, -5), na.rm = TRUE)
## [1] "Calcul vectoriel effectué"
## [1] 2
compte_impair(c(6, 3, 5.5, NA, 0, -5), na.rm = TRUE, methode = c("calcul_vectoriel"))
## [1] "Calcul vectoriel effectué"
## [1] 2
compte_impair(c(6, 3, 5.5, NA, 0, -5), na.rm = TRUE, methode = c("boucle"))
## [1] "Boucle effectuée"
## [1] 2
compte_impair(c(6, 3, 5.5, NA, 0, -5), na.rm = TRUE, methode = c("autre"))
## Error in match.arg(methode) :
## 'arg' should be one of “calcul vectoriel”, “boucle” Créez une fonction qui peut prendre en entrée n’importe quels arguments, en n’importe quelle quantité, et qui ne fait que retourner les noms des arguments qui lui ont été fournis en entrée.
Utilisez la fonction lapply pour remplacer la boucle
suivante, qui produit un histogramme pour chacune des variables du jeu
de données quakes.
for (nom_variable in names(quakes)) {
hist(
x = quakes[, nom_variable],
xlab = nom_variable,
main = paste("Variable", nom_variable, "du jeu de données quakes")
)
}
# À remplacer
for (nom_variable in names(quakes)) {
hist(
x = quakes[, nom_variable],
xlab = nom_variable,
main = paste("Variable", nom_variable, "du jeu de données quakes")
)
}
# Appel à la fonction lapply équivalent à la boucle précédente
lapply(names(quakes), FUN = function(nom_variable) {
hist(
x = quakes[, nom_variable],
xlab = nom_variable,
main = paste("Variable", nom_variable, "du jeu de données quakes")
)
})