IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Tracer des graphiques dans une interface paramétrable Tkinter

Objectif : tracer les graphiques de la loi binomiale et de la loi normale dans une interface Tkinter afin de montrer leur convergence.

Niveau requis : débutant

Commentez cet article : Commentez Donner une note à l´article (5)

Article lu   fois.

L'auteur

Profil Pro

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Une loi binomiale peut être utilisée pour modéliser des situations simples de succès ou échec, un jeu de pile ou face par exemple. Le calcul de sa fonction de masse devient rapidement fastidieux lorsque le nombre d'épreuves n est grand, il est alors possible d'utiliser des approximations par d'autres lois de probabilité telle que la loi normale et d'utiliser des tables de valeurs.

Après avoir défini ces lois de probabilité, on va ensuite montrer comment les représenter graphiquement en Python à l'aide de la librairie matplotlib.

Enfin, on va créer une interface paramétrable Tkinter intégrant un graphique afin de montrer la convergence de loi binomiale vers la loi normale conformément au théorème de Moivre-Laplace.

II. Lois de probabilité

II-A. Loi binomiale

D'après Wikipédia, la loi binomiale est une loi de probabilité discrète décrite par deux paramètres : n le nombre d'expériences réalisées, et p la probabilité de succès. Pour chaque expérience appelée épreuve de Bernoulli, on utilise une variable aléatoire qui prend la valeur 1 lors d'un succès et la valeur 0 sinon. La variable aléatoire, somme de toutes ces variables aléatoires, compte le nombre de succès et suit une loi binomiale. Il est alors possible d'obtenir la probabilité de k succès dans une répétition de n expériences :

kitxmlcodelatexdvpP\left( X=k \right) = \binom{n}{k} p^{k} \left( 1-p \right)^{n-k}finkitxmlcodelatexdvp

II-B. Loi normale

La loi normale est une loi de probabilité continue qui dépend de deux paramètres : son espérance, un nombre réel noté μ, et son écart-type, un nombre réel positif noté σ. La densité de probabilité de la loi normale d'espérance μ et d'écart-type σ est donnée par :

kitxmlcodelatexdvpf(x) = \frac{1}{\sigma\sqrt{2\pi}} \ e^{\textstyle -\frac{1}{2} {\left(\frac{x - \mu}{\sigma}\right)}^2}finkitxmlcodelatexdvp

Parmi les lois de probabilité, les lois normales prennent une place particulière grâce au théorème central limite. En effet, elles correspondent au comportement, sous certaines conditions, d'une suite d'expériences aléatoires similaires et indépendantes lorsque le nombre d'expériences est très élevé. Grâce à cette propriété, une loi normale permet d'approcher d'autres lois comme la loi binomiale et ainsi de modéliser de nombreuses études scientifiques comme des mesures d'erreurs ou des tests statistiques, en utilisant par exemple les tables de la loi normale centrée réduite.

III. Théorème de Moivre-Laplace

D'après Wikipédia, en théorie des probabilités, selon le théorème de Moivre-Laplace, si la variable Xn suit une loi binomiale d'ordre n et de paramètre p ϵ [0, 1], alors la variable :

kitxmlcodelatexdvpZ_n = \frac{X_n - np}{\sqrt{np\left( 1-p \right)}}finkitxmlcodelatexdvp

converge en loi vers une loi normale centrée et réduite N(0, 1). Cette approximation est bonne en général pour np(1 − p) ≥ 10.

IV. Implémentation en Python

IV-A. Fonctions de probabilité

Les fonctions et les objets décrits par la suite sont issus du module scipy.stats.

IV-A-1. Fonction de masse de la loi binomiale

L'objet binom représente une variable aléatoire discrète suivant une loi binomiale qui est en fait une instance de la classe rv_discrete avec ses différentes méthodes.

La fonction de masse de la loi binomiale binom.ppf(x, n, p) peut être appelée comme ceci :

 
Sélectionnez
x = 10; n = 100; p = 0.5
                    
val = binom.ppf(x, n, p)


Traçons maintenant l'histogramme de la fonction avec la librairie matplotlib :

 
Sélectionnez
from scipy.stats import binom
import matplotlib.pyplot as plt
from math import sqrt

# nombre d'épreuves de Bernoulli
n = 80

# probabilité de succès
p = 0.5

# moyenne μ et écart-type σ de la loi binomiale
μ = n*p
σ = sqrt(n*p*(1-p))

# génère la séquence des x : 0 -> n-1
x = range(n)

# nom et dimension de la figure contenant le graphique
plt.figure(num="Figure : Loi binomiale", figsize=(8, 5), dpi=80)

# trace l'histogramme correspondant à la série de valeurs
plt.bar(x, binom.pmf(x,n,p), color="blue")

# limites sur l'axe des x : [μ - 4σ, μ + 4σ]
plt.xlim(μ - 4*σ, μ + 4*σ)

# limite inférieure sur l'axe des y
plt.ylim(0)

plt.title("Histogramme de la loi binomiale B({0}, {1})".format(n,p))

# affiche le graphique
plt.show()


Le code affiche :

Histogramme de la loi binomiale
Histogramme de la loi binomiale

IV-A-2. Fonction de densité de la loi normale

L'objet norm représente une variable aléatoire continue suivant une loi normale qui est en fait une instance de la classe rv_continuous avec ses différentes méthodes.

La fonction de densité de la loi normale norm.pdf(x, loc=μ, scale=σ) d'espérance μ et d'écart-type σ peut être invoquée comme ceci :

 
Sélectionnez
x = 10; μ = 50; σ = 5
                    
val = norm.pdf(x, loc=μ, scale=σ)


Traçons maintenant la courbe représentative de la fonction :

 
Sélectionnez
from scipy.stats import norm
import matplotlib.pyplot as plt
from math import sqrt

# nombre d'épreuves de Bernoulli
n = 80

# probabilité de succès
p = 0.5

# moyenne μ et écart-type σ de la loi normale
μ = n*p
σ = sqrt(n*p*(1-p))

# génère la séquence des x : 0 -> n-1
x = range(n)

# nom et dimension de la figure contenant le graphique
plt.figure(num="Figure : Loi normale", figsize=(8, 5), dpi=80)

# trace la courbe correspondant à la série de valeurs
plt.plot(x, norm.pdf(x,μ,σ), color="red")

# limites sur l'axe des x : [μ - 4σ, μ + 4σ]
plt.xlim(μ - 4*σ, μ + 4*σ)

# limite inférieure sur l'axe des y
plt.ylim(0)

plt.title("Courbe représentative de la loi normale N({0}, {1})".format(round(μ,2),round(σ**2,2)))

# affiche le graphique
plt.show()


Le code affiche :

Courbe de Gauss
Courbe de Gauss

IV-B. Représentation graphique : intégration du graphique dans une interface Tkinter

Nous allons maintenant créer une interface paramétrable avec Tkinter sur laquelle nous allons pouvoir choisir le nombre d'expériences n et la probabilité de succès p de la loi binomiale, puis tracer le graphique des deux fonctions.

La classe tkinter.Tk permet de construire un widget Tk de niveau supérieur, qui est généralement la fenêtre principale d'une application, et initialise un interpréteur Tcl pour ce widget. Chaque instance a son propre interpréteur Tcl associé.

Notre interface est ainsi construite à l'aide d'une classe fille InterfaceGraphique qui hérite de la classe mère tkinter.Tk. On peut alors utiliser les attributs et méthodes de cette classe mère :

Héritage
Héritage

Au moment de créer l'interface Tkinter, c'est-à-dire quand la classe InterfaceGraphique(Tk) est instanciée, on met à jour les zones de texte, puis on trace les graphiques des deux fonctions :

 
Sélectionnez
from tkinter import *
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from math import sqrt
                
class InterfaceGraphique(Tk):
    
    def __init__(self, n, p, pmf, pdf):
        
        # instantiation de la classe parente
        Tk.__init__(self)

        # conteneur vertical occupant tout le formulaire et destiné à contenir le widget à canvas  
        verticalPane = PanedWindow( self, orient=VERTICAL )

        # conteneur horizontal placé en haut du formulaire pour les différents contrôles du formulaire
        horizontalPane = PanedWindow( verticalPane, orient=HORIZONTAL )

        # création des labels et des zones de texte
        lblNbreEpreuves = Label( horizontalPane, text = "Nombre d'épreuves (n) :")  
        self.txtNbreEpreuves= Text(horizontalPane, height = 1, width = 8)
        
        lblProbaSucces = Label( horizontalPane, text = "Proba de succès (p) :")  
        self.txtProbaSucces= Text(horizontalPane, height = 1, width = 8)

        lblMoyenne = Label( horizontalPane, text = "Moyenne (μ) :")  
        self.txtMoyenne= Text(horizontalPane, height = 1, width = 8, bg="lightgray")

        lblEcartType = Label( horizontalPane, text = "Ecart-type (σ) :") 
        self.txtEcartType = Text(horizontalPane, height = 1, width = 8, bg="lightgray")

        # création du bouton de commande pour générer le graphique sur l'interface Tkinter
        btnTracer=Button( horizontalPane, text="Tracer", command=self.btnTracerClicked, width = 10)

        # ajout des contrôles au conteneur horizontal
        horizontalPane.add( lblNbreEpreuves )
        horizontalPane.add( self.txtNbreEpreuves )

        horizontalPane.add( lblProbaSucces )
        horizontalPane.add( self.txtProbaSucces )

        horizontalPane.add( lblMoyenne )
        horizontalPane.add( self.txtMoyenne )


        horizontalPane.add( lblEcartType )
        horizontalPane.add( self.txtEcartType )

        horizontalPane.add( btnTracer )

        # ajout du conteneur horizontal
        verticalPane.add( horizontalPane )
        verticalPane.pack(expand=True, fill='both')

        # ajout de l'objet au conteneur vertical
        verticalPane.pack(expand=True, fill='both')

        # saisie des valeurs par défaut dans les zones de texte
        self.txtNbreEpreuves.insert(END,n)
        self.txtProbaSucces.insert(END,p)
    
        # moyenne μ et écart-type σ de la loi binomiale et de la normale
        μ = n*p
        σ = math.sqrt(n*p*(1-p))

        # mise à jour des zones de texte correspondantes
        self.txtMoyenne.insert(END,round(μ,2))
        self.txtEcartType.insert(END,round(σ,2))

        self.pmf = pmf
        self.pdf = pdf

        # trace le graphique
        self.tracer(n, p, μ, σ)


    def tracer(self, n, p, μ, σ, new_graph=False):
        # méthode permettant de tracer les graphiques sur l'interface

        # génère la séquence des x : 0 -> n-1
        x = range(n)
        
        # on crée la figure du graphique pour les 2 séries de valeurs
        fig = Figure(figsize=(8, 5), dpi=96)
        plt = fig.add_subplot(111)
        
        # trace l'histogramme et la courbe correspondant aux 2 séries de valeurs
        plt.bar(x, self.pmf(x,n,p), color="blue", label = "B({0}, {1})".format(n,p))
        plt.plot(x, self.pdf(x,μ,σ), color="red", label = "N({0}, {1})".format(round(μ,2),round(σ**2,2)))
        
        # limites sur l'axe des x : [μ - 4σ, μ + 4σ]
        plt.set_xlim(μ - 4*σ, μ + 4*σ)

        # limite inférieure sur l'axe des y
        plt.set_ylim(0)

        plt.set_title("Représentation graphique de la loi binomiale et de la loi normale")
        
        plt.legend()
        
        if new_graph:
            self.graph.get_tk_widget().pack_forget()
            
        self.graph = FigureCanvasTkAgg(fig, master=self)
        self.graph.get_tk_widget().pack()


Un bouton de commande btnTracerClicked permet ensuite de tracer le graphique en fonction des choix de paramètres n et p :

 
Sélectionnez
class InterfaceGraphique(Tk): 

    ...

    def btnTracerClicked(self):
    # méthode qui s'exécute quand on clique sur le bouton de commande btnTracer

        # copie du contenu des zones de texte dans des variables
        n = int(self.txtNbreEpreuves.get("1.0",'end-1c'))
        p = float(self.txtProbaSucces.get("1.0",'end-1c'))

        # moyenne μ et écart-type σ de la loi binomiale et de la normale
        μ = n*p
        σ = math.sqrt(n*p*(1-p))

        # mise à jour des zones de texte correspondantes
        self.txtMoyenne.delete("1.0",'end-1c')
        self.txtMoyenne.insert(END,round(μ,2))

        self.txtEcartType.delete("1.0",'end-1c')
        self.txtEcartType.insert(END,round(σ,2))

        # trace le graphique
        self.tracer(n,p,μ,σ,True)


Testons maintenant notre interface graphique :

 
Sélectionnez
from scipy.stats import binom, norm
from interface_graphique import InterfaceGraphique

# nombre d'épreuves de Bernoulli
n = 80

# probabilité de succès
p = 0.5

# création de l'objet InterfaceGraphique avec les paramètres : n, p, binom.pmf, norm.pdf
InterfaceGraphique = InterfaceGraphique(n, p, binom.pmf, norm.pdf)

# ajout d'un titre à la fenêtre Tkinter
interface_graphique.title("Interface graphique avec Tkinter")

# centre la fenêtre
InterfaceGraphique.eval('tk::PlaceWindow . center')

InterfaceGraphique.mainloop()


Le code affiche :

Interface Tkinter
Interface Tkinter

Le graphique montre bien que la valeur en x de la fonction de densité de la loi normale représente une bonne approximation de la valeur en x de la fonction de masse de la loi binomiale pour n=80 et p=0.5.

IV-C. Module Python

On donne pour finir le code complet du module présent dans le fichier joint dossier_test.zipdossier de test :

 
Cacher/Afficher le codeSélectionnez

V. Conclusion

Après avoir défini la loi binomiale et la loi normale, on a donc présenté le théorème de Moivre-Laplace comme un cas particulier du théorème central limite.

On a pu ensuite montrer comment représenter graphiquement ces lois à l'aide de la librairie matplotlib, et comment tracer leur graphique dans une interface Tkinter afin de vérifier que la loi binomiale converge bien vers la loi normale quand n augmente.

VI. Téléchargement

Le dossier de testdossier de test :

  • interface_graphique.py : module contenant la classe InterfaceGraphique ;
  • representation_graphique.py : module principal.

VII. Remerciements

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Copyright © 2024 Denis Hulo. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.