Développement logiciel Master 1 Biostat / MIND Durée : 2h00 Les notes de cours et l’aide de R sont autorisées. Une très grande importance sera portée sur la rédaction de vos codes. Ainsi usez (abusez ?) de commentaires dans votre code, choisissez de bons noms pour vos variables, veillez à l’indentation. . . (ceci pour avoir une meilleure note) Retenez que chaque figure devra être consciencieusement réalisée. Vous voilà prévenu ! ! ! Vous me remettrez votre code sur une clé USB et le nom de votre fichier sera de la forme Nom-Prénom.R (au format R ou RMarkdown selon vos préférences). Exercice 1 (Réinventons la roue nommée ”hist”). Le but (extrêmement motivant) de cet exercice est de faire un histogramme par nos propres moyens et de comparer notre implémentation à celle fournie de base par R via la fonction hist. a) Faites une fonction R qui pour un échantillon x1 , . . . , xn donné et des classes c1 = (a0 , a1 ), c2 = (a1 , a2 ), . . . , ck = (ak−1 , ak ), calcule les effectifs présents dans chaque classe. b) Importez les données disponibles via le lien suivant http://lib.stat.cmu.edu/DASL/Datafiles/ceodat.html et testez votre fonction développée en a) pour voir si elle semble correcte. c) Faites une fonction qui trace un histogramme de statisticien et testez votre fonction sur les données de salaire importées en b). d) Comparez votre résultat à celui obtenu par la fonction hist de R. Eventuellement conclure sur votre niveau en R. Conseil et contraintes : la fonction rect pourra vous être utile. Cependant il est interdit d’utiliser la fonction table de R pour cet exercice. > effectifs <- function(data, classes){ + n.classes <- length(classes) - 1 + ans <- rep(NA, n.classes) + for (i in 1:n.classes) + ans[i] <- sum((data > classes[i]) & (data <= classes[i+1]), na.rm = TRUE) + + > > + > > return(ans) } data <- read.table("CEOSalaries.txt", header = TRUE, skip = 12, na.string = "*") effectifs(data$SAL, seq(0, 1200, by = 100)) [1] 2 5 18 13 4 6 3 4 3 0 0 1 1 > myhist <- function(data, classes, xlab = "X"){ + eff <- effectifs(data, classes) + + ## Calculs pour un histogramme d'aire 1 car on est des stateux !!!! hauteurs <- eff / (length(data) * diff(classes)) + + + + + > > > > > plot(0, xlim = range(classes), ylim = c(0, max(hauteurs)), type = "n", xlab = xlab, ylab = "Densite") rect(classes[-length(classes)], rep(0, length(classes)-1), classes[-1], hauteurs) } 0.0030 0.0020 0.0000 0.0010 Density 0.0020 0.0010 0.0000 Densite 0.0030 classes <- seq(0, 1200, by = 100) par(mfrow = c(1, 2)) myhist(data$SAL, classes, xlab = "Salaire") hist(data$SAL, classes, freq = FALSE, main = "", xlab = "Salaire") 0 200 400 600 800 1000 1200 0 200 Salaire 400 600 800 1000 1200 Salaire > ## On obtient pareil et nous sommes trop fort en R !!! PPP Exercice 2 (Un algorithme bien connu en stats !). L’algorithme de Metropolis–Hastings est largement utilisé en statistique. Cet algorithme permet de générer une chaı̂ne de Markov {Xt : t ≥ 0} dont la loi stationnaire est imposée à l’avance. Nous allons ici utiliser cet algorithme afin de générer des variables aléatoires selon une loi Normale centrée réduite. Voici une version de cet algorithme. 1. Prendre un état initial X0 pour la chaine de Markov et fixez la longueur N de la chaı̂ne à générer ; 2. Pour t = 0, . . . , N − 2 faire : a) Simuler un état candidat X∗ ∼ Xt + U (−0.5, 0.5) ; 2 b) Calculer la probabilité d’acceptation de ce candidat ϕ(X∗ ) α(Xt → X∗ ) = min 1, , ϕ(Xt ) où ϕ(·) représente la densité de probabilité d’une N (0, 1). c) Poser Xt+1 ( X∗ , avec probabilité α(Xt → X∗ ) = Xt , avec probabilité 1 − α(Xt → X∗ ). 3. Renvoyez la chaı̂ne {Xt : t = 0, . . . , N − 1}. a) Créez une fonction R implémentant l’algorithme décrit plus haut. b) Exécutez votre algorithme avec N = 20000 et tracez un histogramme sur les 10000 derniers états de la chaı̂ne. Superposez la densité de probabilité d’une N (0, 1) sur cet histogramme. Concluez ? Astuce : Pour générer une variable aléatoire donnée par ( a, avec probabilité p Y = b, avec probabilité 1 − p, il suffit simplement de générer U ∼ U (0, 1) et poser Y = a si U < p et Y = b sinon. > mh <- function(N, init = 0){ + chain <- rep(NA, N) + chain[1] <- init + for (i in 1:(N-1)){ + prop <- chain[i] + runif(1, -0.5, 0.5) + alpha <- min(1, dnorm(prop) / dnorm(chain[i])) + if (runif(1) < alpha) + chain[i+1] <- prop + else + chain[i+1] <- chain[i] + } + + > > > + > return(chain) } chain <- mh(20000) hist(chain[-(1:9999)], freq = FALSE, main = "", xlab = "x", ylim = c(0, 1 / sqrt(2 * pi))) plot(dnorm, from = -4, to = 4, col = "orange", add = TRUE) 3 0.4 0.3 0.2 0.0 0.1 Density −3 −2 −1 0 1 2 3 x PPP Exercice 3 (Urnes d’Ehrenfest). Les urnes d’Ehrenfest est un modèle probabiliste fortement lié au mouvement des particules. Nous allons l’étudier sous sa forme puces et chiens . . . Deux chiens Médor et Rosco se partagent N puces dans le sens où chaque matin au réveil une des N puces est tirée au hasard et change alors de chien. Mathématiquement cela pourrait s’écrire ainsi. Soit {Xt : t ≥ 0} le nombre de puces de Rosco au matin du t-ème jour. a) Créez une fonction dont le but est de simuler la dynamique des puces sur Médor et Rosco . Votre fonction prendra comme arguments : le nombre de puces N , le nombre de puces initialement sur Rosco NRosco ainsi que le nombre de jours T pour notre recensement de puces. b) Faites tourner votre fonction pour N = 100, T = 2 × 365 et NRosco = 50 afin de représenter graphiquement l’évolution du nombre de puces sur Rosco au cours du temps. > ehrenfest <- function(nb.puces = 100, puces.rosco = 0.5 * nb.puces, + duree = 2 * 365){ + rosco <- 1:puces.rosco + + ans <- rep(NA, duree + 1) ans[1] <- puces.rosco + + for (i in 1:duree){ puce.idx <- sample(nb.puces, 1) + + + if (puce.idx %in% rosco) rosco <- rosco[rosco != puce.idx] else 4 + rosco <- c(rosco, puce.idx) + + return(ans) } nb.puces <- 100 nb.puces.rosco <- 0.5 * nb.puces duree <- 2 * 365 0 20 40 60 80 100 ans <- ehrenfest(nb.puces, nb.puces.rosco, duree) plot(ans, type = "h", xlab = "Jours", ylab = "Nombre de puces sur Rosco", ylim = c(0, nb.puces)) Nombre de puces sur Rosco + + > > > > > > > + ans[i+1] <- length(rosco) } 0 200 400 Jours PPP 5 600