ÉTUDE SIMPLIFIÉE D'UNE DÉRIVE GÉNÉTIQUE : MODÉLISATION ET MISE EN ŒUVRE AVEC R (A PARTIR D'UN CAS PROPOSÉ EN PLURI PAR FABRICE LECLERCQ) CAS CONCRET ET PREMIÈRE MODÉLISATION (MODÈLE A) L'exemple est tiré du livre "Guide critique de l'évolution", sous la direction de Guillaume Lecointre, (éditions Belin). Un travail avec les enseignants de biologie doit permettre de préciser la problématique biologique. Il s'agit d'étudier l'évolution des espèces d'une population d'escargots, tout au long de plusieurs générations. On modélise une évolution particulière en partant des hypothèses suivantes : H1 : La population est isolée (sur un îlot), il n'y a donc pas d'apport extérieur. H2 : La population de départ est constituée de 6 individus de 6 espèces différentes que l'on appellera au départ "Blanc", "Bleu", "Rouge", "Jaune", "Vert", "Noir" puis, pour des raisons pratiques de programmation, "violet", "blue", "red", "yellow", "green", "black". H3 : À chaque génération, chaque espèce donne naissance à un nombre de petits de 1 à 6, aléatoirement distribué selon une loi uniforme discrète. L'ensemble de tous ces petits constitue la population initiale (de départ) de chaque génération. H4 : À chaque génération, ne survivent que 6 individus choisis au hasard dans la population initiale de la génération en cours. H5 : Ces 6 individus se reproduisent selon l'hypothèse H3, les génération se succèdent donc de la même façon. L'étude portera sur les 4 aspects suivants : aspect 1 : Le nombre et le pourcentage de chaque espèce au début de chaque génération, avec une présentation dynamique. aspect 2 : L'évolution, au cours des générations, du nombre d'individus de l'espèce qui reste seule au bout d'un certain nombre de générations. aspect 3 : La distribution du nombre de générations au bout duquel une espèce se retrouve seule sur l'îlot. aspect 4 : La distribution des espèces se retrouvant seules au bout d'un certain nombre de générations. L'utilisation de RStudio (ou Tinn-R en réorganisant les fenêtres de façon appropriée) permet de répéter directement la même simulation (touches ↑ puis entrée) et d'observer l'effet graphique des variations des distributions ou des fonctions obtenus à partir des séries simulées (cf. les copies d'écran en dernières pages). PREMIÈRE MISE EN ŒUVRE DU MODÈLE A, EN LIGNES DE COMMANDES POUR COMPRENDRE LES FONCTION R UTILISÉES ► Il s'agit d'observer l'évolution de la distribution des effectifs des espèces en début de chaque génération. # DÉRIVE GÉNÉTIQUE CHEZ LES ESCARGOTS # LES COMMANDES DE FABRICE LECLERCQ # Simuler le jet d'un dé (dai) (dai <- 1:6) [1] 1 2 3 4 5 6 sample(dai, 1) [1] 2 sample(dai, 6) [1] 1 4 3 6 5 2 sample(dai, 6, replace = TRUE) [1] 6 2 5 5 5 3 Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS page 1 sur 11 07/12/12 * DeriveEscargots.odt # Création de l'îlot initial (population parent) ilot <- c("Blanc", "Bleu", "Rouge", "Jaune", "Vert", "Noir") table(ilot) ilot Blanc Bleu Jaune Noir Rouge Vert 1 1 1 1 1 1 pie(table(ilot)) # La reproduction à la génération 1 (population <- rep(ilot, sample(dai, [1] "Blanc" "Blanc" "Blanc" "Blanc" [10] "Rouge" "Rouge" "Rouge" "Jaune" [19] "Noir" "Noir" "Noir" "Noir" 6, replace = TRUE))) "Blanc" "Blanc" "Bleu" "Bleu" "Rouge" "Jaune" "Jaune" "Jaune" "Jaune" "Vert" "Noir" "Noir" # Tableau des effectifs de la distribution des espèces au début de la génération 1 : (tabloEspeces <- table(population)) population Blanc Bleu Jaune Noir Rouge Vert 6 2 5 6 4 1 # Tableau des fréquences de la distribution des espèces au # début de la génération 1 : (tablEspeces <- tabloEspeces / sum(tabloEspeces)) population Blanc Bleu Jaune Noir Rouge Vert 0.250 0.083 0.208 0.250 0.167 0.042 pie(tablEspeces, labels = paste(names(tablEspeces), "\n", round(tablEspeces, 2))) # Sur l'îlot la sélection naturelle fait que seuls 6 escargots choisis au # hasard vont survivre et se reproduire. On aura alors la génération 2 ilot <- sample(population, 6) [1] "Noir" "Jaune" "Noir" "Blanc" "Rouge" "Blanc" # Et le cycle recommence, pour aboutir à la génération 2 : (population <- rep(ilot, sample(dai, 6, replace = TRUE))) [1] "Noir" "Noir" "Noir" "Noir" "Jaune" "Jaune" "Jaune" "Noir" "Noir" [10] "Noir" "Blanc" "Blanc" "Blanc" "Blanc" "Blanc" "Blanc" "Rouge" "Rouge" [19] "Rouge" "Rouge" "Blanc" "Blanc" "Blanc" "Blanc" "Blanc" "Blanc" (tabloEspeces <- table(population)) population Blanc Jaune Noir Rouge 12 3 7 4 (tablEspeces <- tabloEspeces / sum(tabloEspeces)) population Blanc Jaune Noir Rouge 0.4615385 0.1153846 0.2692308 0.1538462 pie(tablEspeces, labels = paste(names(tablEspeces), "\n", round(tablEspeces, 2))) Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS page 2 sur 11 07/12/12 * DeriveEscargots.odt DEUXIÈME MISE EN ŒUVRE DU MODÈLE A AVEC UNE FONCTION R PLUS PRATIQUE À UTILISER ► On fait afficher la successions des tableaux des effectifs des espèces des populations en début de chaque génération. On fait afficher la succession des graphiques en secteurs des fréquences correspondantes. Une phrase annonce l'espèce restant seule en fin de dérive, au bout de "gen" générations. # F. LECLERCQ PROGRAMME 1 DerivEscar1 <- function(){ dai <- 1:6 ; gen <- 1 ilot <- c("white", "blue", "red", "yellow", "green", "black") while(length(unique(ilot)) > 1){ population <- rep(ilot, sample(dai, 6, replace = TRUE)) ilot <- sample(population, 6) tablEffEspeces <- table(population) cat("Génération numéro", gen, "\n") print(tablEffEspeces) tablFreqEspeces <- tablEffEspeces / sum(tablEffEspeces) pie(tablFreqEspeces, labels = paste(names(tablFreqEspeces), "\n", round(tablFreqEspeces, 2)), col = names(tablEffEspeces), main = paste("Distribution des espèces dans la \n", "population initiale de la génération", gen)) Sys.sleep(3) gen <- gen + 1 } cat("\nLa dérive génétique a abouti à l'unique espèce :\n", unique(ilot), "à la génération", gen, "\n\n") } > DerivEscar1() Génération numéro 1 population black blue green red 2 2 2 5 Génération numéro 2 population black blue red white 3 10 1 4 Génération numéro 3 population blue white 5 10 Génération numéro 4 population blue white 3 18 white yellow 3 1 La dérive génétique a abouti à l'unique espèce : white à la génération 5 Avec les icônes de la fenêtre plot, il est possible de revoir les graphiques en secteur de toutes les générations représentées dynamiquement. Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS page 3 sur 11 07/12/12 * DeriveEscargots.odt TROISIÈME MISE EN ŒUVRE DU MODÈLE A AVEC UNE FONCTION R ► La fonction R réalise un tableau récapitulatif des effectifs de toutes les espèces présentes en début de génération. Elle fait un graphique en ligne brisée de l'évolution de l'effectif de l'espèce qui reste seule sur l'îlot. DerivEscar2 <- function(){ dai <- 1:6 ; gen <- 2 ilot <- c("violet", "blue", "red", "yellow", "green", "black") PopIlots <- table(rep(ilot, sample(dai, 6, replace = TRUE))) names(PopIlots) <- c("black", "blue", "green", "red", "violet", "yellow") while(length(unique(ilot)) > 1){ population <- rep(ilot, sample(dai, 6, replace = TRUE)) ilot <- sample(population, 6) tablEffEspeces <- table(population) tab0 <- rep(0, 6) names(tab0) <- c("black", "blue", "green", "red", "violet", "yellow") tab0[names(tablEffEspeces)] <- tablEffEspeces PopIlots <- rbind(PopIlots, tab0) gen <- gen + 1 } tab0 <- rep(0, 6) names(tab0) <- c("black", "blue","green", "red", "violet", "yellow") tablEffEspeces <- table(ilot) tab0[names(tablEffEspeces)] <- tablEffEspeces PopIlots <- rbind(PopIlots, tab0) rownames(PopIlots) <- paste(rep("generation", gen), 1:gen, sep = "") # Affichages des graphiques et résultats cat("\nLa dérive génétique a abouti à l'unique espèce :\n", unique(ilot), "à la génération", gen, "\n\n") print(PopIlots) plot(1:gen, PopIlots[ , unique(ilot)], type = "l", col = unique(ilot), xlab = "Rang de la génération", ylab = "Effectif de l'espèce restante", main = paste("Évolution de l'effectif de l'espèce", unique(ilot), "\npendant", gen, "générations en début de génération")) } > DerivEscar2() La dérive génétique a abouti à l'unique espèce : red à la génération 12 generation1 generation2 generation3 generation4 generation5 generation6 generation7 generation8 generation9 generation10 generation11 generation12 black blue green red violet yellow 4 6 3 1 4 6 6 4 1 6 6 5 4 0 0 7 8 6 0 0 0 19 6 1 0 0 0 20 8 0 0 0 0 8 7 0 0 0 0 12 6 0 0 0 0 13 9 0 0 0 0 17 5 0 0 0 0 16 7 0 0 0 0 18 1 0 0 0 0 6 0 0 Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS page 4 sur 11 07/12/12 * DeriveEscargots.odt ► Par rapport à DerivEscar2() La fonction R suivante DerivEscar2_1() réalise un graphique supplémentaire en boites à pattes (boxplot) qui est une façon de résumer graphiquement les distributions du nombre d'individus en début de génération, par espèce. C'est aussi une bonne illustration de la "polyvalence" de la fonction grahique plot(...). DerivEscar2_1 <- function(){ dai <- 1:6 ; gen <- 2 ilot <- c("violet", "blue", "red", "yellow", "green", "black") PopIlots <- table(rep(ilot, sample(dai, 6, replace = TRUE))) names(PopIlots) <- c("black", "blue", "green", "red", "violet", "yellow") while(length(unique(ilot)) > 1){ population <- rep(ilot, sample(dai, 6, replace = TRUE)) ilot <- sample(population, 6) tablEffEspeces <- table(population) tab0 <- rep(0, 6) names(tab0) <- c("black", "blue", "green", "red", "violet", "yellow") tab0[names(tablEffEspeces)] <- tablEffEspeces PopIlots <- rbind(PopIlots, tab0) gen <- gen + 1 } tab0 <- rep(0, 6) names(tab0) <- c("black", "blue","green", "red", "violet", "yellow") tablEffEspeces <- table(ilot) tab0[names(tablEffEspeces)] <- tablEffEspeces PopIlots <- rbind(PopIlots, tab0) rownames(PopIlots) <- paste(rep("generation", gen), 1:gen, sep = "") # Affichage du tableau des résultats cat("\nLa dérive génétique a abouti à l'unique espèce :\n", unique(ilot), "à la génération", gen, "\n\n") print(PopIlots) # Représentation graphique en segments de droites plot(1:gen, PopIlots[ , unique(ilot)], type = "l", col = unique(ilot), xlab = "Rang de la génération", ylab = "Effectif de l'espèce restante", main = paste("Évolution de l'effectif de l'espèce", unique(ilot), "\npendant", gen, "générations en début de génération")) # Création des variables pour que plot fasse des boxplot, puis réalisation du graphique # dev.new() # Si on est sous Tinn-R pour une nouvelle fenêtre # Sous RStudio on peut faire défiler tous les graphiques faits nLign <- dim(PopIlots)[1] ; nCol <- dim(PopIlots)[2] y <- PopIlots[, 1] ; for (i in 2:nCol) y <- c(y, PopIlots[, i]) x <- as.factor( rep(c("black", "blue","green", "red", "violet", "yellow"), rep(nLign, nCol))) plot(x, y, main = paste( "Distributions* simulées du nombre d'individus", "\nen début de génération, espèce par espèce", "\nEspèce restant seule =", unique(ilot)), xlab = "Espèces", ylab = "Nombre d'individus", border = levels(x)) } > DerivEscar2_1() La dérive génétique a abouti à l'unique espèce : green à la génération 8 black blue green red violet yellow generation1 2 3 2 4 6 3 generation2 1 6 4 2 4 2 generation3 0 10 2 6 10 0 generation4 0 0 5 11 1 0 generation5 0 0 2 19 0 0 generation6 0 0 6 15 0 0 generation7 0 0 16 5 0 0 generation8 0 0 6 0 0 0 Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS page 5 sur 11 07/12/12 * DeriveEscargots.odt ► Par rapport à DerivEscar2() La fonction R suivante DerivEscar2_2() réalise deux graphiques supplémentaires en points et en boites à pattes horizontales. DerivEscar2_1 <- function(){ dai <- 1:6 ; gen <- 2 especes <- c("black", "blue", "green", "red", "violet", "yellow") ilot <- especes PopIlots <- table(rep(ilot, sample(dai, 6, replace = TRUE))) names(PopIlots) <- especes while(length(unique(ilot)) > 1){ population <- rep(ilot, sample(dai, 6, replace = TRUE)) ilot <- sample(population, 6) tablEffEspeces <- table(population) tab0 <- rep(0, 6) names(tab0) <- especes tab0[names(tablEffEspeces)] <- tablEffEspeces PopIlots <- rbind(PopIlots, tab0) gen <- gen + 1 } tab0 <- rep(0, 6) names(tab0) <- especes tablEffEspeces <- table(ilot) tab0[names(tablEffEspeces)] <- tablEffEspeces PopIlots <- rbind(PopIlots, tab0) rownames(PopIlots) <- paste(rep("generation", gen), 1:gen, sep = "") # Affichage du tableau des résultats cat("\nLa dérive génétique a abouti à l'unique espèce :\n", unique(ilot), "à la génération", gen, "\n\n", "Tableau des effectifs des espèces en début de génération\n") print(PopIlots) # Représentation graphique en segments de droites plot(1:gen, PopIlots[ , unique(ilot)], type = "l", col = unique(ilot), xlab = "Rang de la génération", ylab = "Effectif de l'espèce restante", main = paste("Évolution de l'effectif de l'espèce", unique(ilot), "\npendant", gen, "générations en début de génération")) # Création des variables pour que plot fasse des boxplot, puis réalisation du graphique nLign <- dim(PopIlots)[1] ; nCol <- dim(PopIlots)[2] y <- PopIlots[, 1] ; for (i in 2:nCol) y <- c(y, PopIlots[, i]) x <- as.factor(rep(especes, rep(nLign, nCol))) # Représentation graphique en points, par espèces plot(y, x, pch = 19, col = rep(levels(x), each = nLign), main = paste("Distributions* simulées de l'effectif", "\nen début de génération, espèce par espèce", "\nEspèce restant seule =", unique(ilot)), xlab = "Effectif en debut de génération", ylab = "Espèce", yaxt = "n") axis(side = 2, at = 1:nCol, labels = levels(x)) # Représentation graphique en boites à pattes, par espèces plot(x, y, horizontal = TRUE, main = paste( "Distributions* simulées de l'effectif", "\nen début de génération, espèce par espèce", "\nEspèce restant seule =", unique(ilot)), xlab = "Espèces", ylab = "Nombre d'individus", border = levels(x)) } > DerivEscar2_2() La dérive génétique a abouti à l'unique espèce : red à la génération 8 Tableau des effectifs des espèces en début de génération black blue green red violet yellow generation1 6 4 3 5 2 3 generation2 2 6 4 5 3 1 generation3 0 9 2 5 3 4 generation4 0 11 0 6 0 5 generation5 0 16 0 13 0 0 generation6 0 11 0 13 0 0 generation7 0 2 0 13 0 0 generation8 0 0 0 6 0 0 Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS page 6 sur 11 07/12/12 * DeriveEscargots.odt QUATRIÈME MISE EN ŒUVRE DU MODÈLE A AVEC UNE FONCTION R ► La fonction R simule une distribution du nombre de générations nécessaires pour aboutir à une espèce unique. Elle fait un graphique en barres de cette distribution simulée. DerivEscar3 <- function(nbsim = 2000){ dai <- 1:6 ; SeriGen <- NULL for(i in 1:nbsim){ gen <- 1 ilot <- c("violet", "blue", "red", "yellow", "green", "black") while(length(unique(ilot)) > 1){ population <- rep(ilot, sample(dai, 6, replace = TRUE)) ilot <- sample(population, 6) gen <- gen + 1 } SeriGen <- c(SeriGen, gen) } DistFreqGen <- table(SeriGen) / nbsim # Affichage des résultats et des graphiques cat("Tableau d'une distribution* simulée du nombre\n", "de générations pour arriver à une espèce unique\n") print(DistFreqGen) plot(DistFreqGen, xlab = "Nombre de générations", # À comparer avec barplot(...) ylab = "Fréquences* simulées", main = paste("Distribution* simulées du nombre de générations\n", "pour arriver à une seule espèce")) } > DerivEscar3() Tableau d'une distribution* de générations pour arriver SeriGen 3 4 5 6 0.0070 0.0415 0.0745 0.0970 10 11 12 13 0.0750 0.0615 0.0535 0.0475 17 18 19 20 0.0235 0.0185 0.0145 0.0125 24 25 26 27 0.0070 0.0055 0.0035 0.0035 31 32 34 35 0.0030 0.0005 0.0025 0.0020 40 41 42 45 0.0010 0.0005 0.0005 0.0005 Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS simulée du nombre à une espèce unique 7 0.1090 14 0.0450 21 0.0090 28 0.0040 36 0.0015 52 0.0005 8 0.0965 15 0.0360 22 0.0085 29 0.0010 37 0.0010 9 0.0930 16 0.0250 23 0.0090 30 0.0030 38 0.0015 page 7 sur 11 07/12/12 * DeriveEscargots.odt CINQUIÈME MISE EN ŒUVRE DU MODÈLE A AVEC UNE FONCTION R ► La fonction R simule, cette fois, une distribution des espèces restant seules au bout de x générations. DerivEscar4 <- function(nbsim = 2000){ dai <- 1:6 ; SeriEspece <- NULL for(i in 1:nbsim){ ilot <- c("violet", "blue", "red", "yellow", "green", "black") while(length(unique(ilot)) > 1){ population <- rep(ilot, sample(dai, 6, replace = TRUE)) ilot <- sample(population, 6) } SeriEspece <- c(SeriEspece, unique(ilot)) } DistFreqEspece <- table(SeriEspece) / nbsim # Affichage des résultats et des graphiques cat("Tableau d'une distribution* simulée\n", "des espèce restant seules au bout de x générations\n") print(DistFreqEspece) plot(DistFreqEspece, xlab = "Espèces", # À comparer avec barplot() ylab = "Fréquences* simulées", col = c("black", "blue","green", "red", "violet", "yellow"), main = paste("Distribution* simulée\n", "des espèces restant seules")) } > DerivEscar4() Tableau d'une distribution* restant seules au bout de x SeriEspece black blue green red 0.1780 0.1645 0.1655 0.1655 Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS simulées des espèce générations violet yellow 0.1605 0.1660 page 8 sur 11 07/12/12 * DeriveEscargots.odt RÉPÉTER DES SIMULATIONS AVEC RSTUDIO La simulation est une fonction R. Pour répéter la simulation il suffit donc de rappeler la fonction à l'aide des touches ↑ puis entrée, autant de fois que l'on veut. Avec RStudio, les fenêtres de travail étant positionnées automatiquement cela se fait très facilement : 1° Ouvrir le fichier (R_DeriveEscargots.r) contenant les lignes de code de plusieurs simulations et de plusieurs fonctions. 2° Dans la fenêtre "source", sélectionner les lignes de code de la fonction concernée (par exemple DerivEscar2()). Si le fichier ne contient que le code d'une seule fonction, il n'est pas nécessaire de sélectionner les lignes de code. On peut alors directement passer à l'étape suivante. 3° Charger en mémoire les lignes de code sélectionnées en cliquant sur l’icône . Dans le cas d'une seule fonction dans le fichier R, cliquer sur pour charger toute le code de la fonction. Le nom de la fonction s'affiche dans la fenêtre "Workspace". 4° "Lancer" la fonction en tapant DerivEscar2() dans la fenêtre "console". Les résultats numériques s'affichent dans la fenêtre "console", les graphiques dans la fenêtre "Plots". 5° Pour relancer la simulation, il suffit, dans la fenêtre "console", de rappeler la fonction DerivEscar2()avec la touche ↑ puis puis de la lancer en appuyant sur entrée. On observe les effets dans la fenêtre "graphique". Des exemples avec les fonctions DerivEscar2() et DerivEscar3() figurent dans les pages suivantes. ► On peut faire défiler, dans la fenêtre "Plot", avec les icônes , tous les graphiques faits depuis le début de la session. À utiliser sans modération, par exemple avec les résultats de la fonction DerivEscar1(). POLYVALENCE DE LA FONCTION PLOT(...) Il est intéressant d'observer les différents types de graphiques produits par la fonction plot, en fonction de la nature des variables (objets) utilisé(e)s comme arguments. Cette fonction peut produire un nuages de points, un ensemble de nuages de points, un diagramme en barres, en lignes ou en points, une série de boites à pattes, selon que la variable représentée en abscisse est quantitative ou qualitative (catégorielle). Un document spécifique présentera ces différents aspects. Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS page 9 sur 11 07/12/12 * DeriveEscargots.odt Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS page 10 sur 11 07/12/12 * DeriveEscargots.odt Hubert RAYMONDAUD LEGTA LOUIS GIRAUD 84200 CARPENTRAS page 11 sur 11 07/12/12 * DeriveEscargots.odt