Mathématice, intégration des Tice dans l'enseignement des mathématiques  
Sommaire > N°66 - Septembre 2019 > Les algorithmes du programme de Mathématiques (...)

Les algorithmes du programme de Mathématiques de Première technologique (2019).
Moteur de recherche
Mis en ligne le 5 mai 2019, par Benjamin Clerc

Cet article peut être librement diffusé et son contenu réutilisé pour une utilisation non commerciale (contacter l’auteur pour une utilisation commerciale) suivant la licence CC-by-nc-sa

Dans le programme de mathématiques de première technologique, on trouve parmi la liste des compétences mathématiques travaillées :
- Calculer, appliquer des techniques et mettre en œuvre des algorithmes ;
Il y a dans ce programme des indications au sujet de ces algorithmes que l’on peut mettre en œuvre, nous allons ici les illustrer.
Nous faisons le choix de vous proposer une approche 100% fonctionnelle, comme préconisé dans les programmes.
Ceci concerne toutes les séries technologiques sauf la série STD2A.

Algorithmique et programmation
La pratique de l’algorithmique et de la programmation se poursuit au cycle terminal. En continuité avec la classe de seconde, le langage utilisé est Python. Le programme vise la consolidation des notions de variable, d’instruction conditionnelle et de boucle ainsi que l’utilisation des fonctions. La seule notion nouvelle est celle de liste qui trouve naturellement sa place dans de nombreuses parties du programme et aide à la compréhension de notions mathématiques telles que les suites numériques, les tableaux de valeurs, les séries statistiques...
Capacités attendues

Variables

- utiliser un générateur de nombres aléatoires entre 0 et 1 pour simuler une loi de Bernoulli de paramètre p ;
La loi de Bernoulli de paramètre p peut être simulée en coupant l’intervalle [0,1] en deux sous-intervalles, l’un de taille p, l’autre de taille 1−p :

  1. >>> from random import random
  2. >>> p=0.7
  3. >>> if random()<p:
  4. print(1)
  5. else:
  6. print(0)
  7. 1

Télécharger


- utiliser la notion de compteur ;
Lorsque l’on souhaite répéter un nombre donné de fois la même instruction ou le même bloc d’instructions, la commande for est la plus appropriée. Elle intègre un compteur, souvent appelé i (on peut lui donner le nom que l’on veut)
Admettons que l’on veuille répéter 7 fois la loi de Bernoulli de paramètre p ci-dessus. Voici ce que l’on peut faire.

  1. >>> from random import random
  2. >>> p=0.7
  3. >>> for i in range(7):
  4. if random()<p:
  5. print(1)
  6. else:
  7. print(0)
  8. 0
  9. 0
  10. 0
  11. 1
  12. 1
  13. 1
  14. 0

Télécharger

Lorsque l’on souhaite répéter un certain nombre de fois, inconnu, la même instruction ou le même bloc d’instructions, la commande while est la plus appropriée et le plus souvent elle nécessite un compteur. On va répéter la loi de Bernoulli de paramètre p jusqu’à ce qu’elle ait rencontré 10 succès.

  1. >>> from random import random
  2. >>> compteur=0
  3. >>> p=0.7
  4. >>> while compteur<10:
  5. if random()<p:
  6. print(1)
  7. compteur+=1
  8. else:
  9. print(0)
  10. 1
  11. 1
  12. 0
  13. 1
  14. 0
  15. 1
  16. 0
  17. 1
  18. 1
  19. 0
  20. 0
  21. 1
  22. 0
  23. 1
  24. 0
  25. 1
  26. 1

Télécharger


- utiliser le principe d’accumulateur pour calculer une somme, un produit.
On s’est servi de ce principe pour incrémenter le compteur ci-dessus, mais illustrons cela avec un calcul de somme, par exemple les carrés des nombres inférieurs à 10 :

  1. >>> somme=0
  2. >>> for i in range(10):
  3. somme+=i**2
  4. >>> print(somme)
  5. 285

Télécharger

Commentaires
- Les notions relatives aux types de variables et à l’affectation sont consolidées. Comme en classe de seconde, on utilise le symbole « ← » pour désigner l’affectation dans un algorithme écrit en langage naturel.
Python est un langage à typage dynamique, ce qui signifie que la valeur que l’on affecte à une variable définit son type. Le type du contenu d’une variable peut donc changer si on change sa valeur.
La fonction type()
Pour connaître le type d’une donnée ou d’une variable, il suffit d’utiliser la fonction type().

  1. >>> type(6)
  2. <class 'int'>
  3. >>> a = 6
  4. >>> type(a)
  5. <class 'int'>
  6. >>> a = "math"
  7. >>> type(a)
  8. <class 'str'>
  9. >>> a = 6.1
  10. >>> type(a)
  11. <class 'float'>

Télécharger

Le type int (entier)
Ce type est utilisé pour stocker un entier ( integer en anglais).

  1. >>> type(1234)
  2. <class 'int'>

Télécharger

Le type float (flottant)
Ce type est utilisé pour stocker des nombres à virgule flottante ( floating point numbers en anglais). En français, on parle de flottant.

  1. >>> a=12.3
  2. >>> type(a)
  3. <class 'float'>
  4. >>> a=6.
  5. >>> type(a)
  6. <class 'float'>
  7. >>> a
  8. 6.0
  9. >>> a = 2.99792458e8
  10. >>> a
  11. 299792458.0
  12. >>> type(a)
  13. <class 'float'>

Télécharger

Le type str (chaîne de caractères)
Dans Python, une donnée de type str est une suite quelconque de caractères délimitée soit par des apostrophes, soit par des guillemets. str est l’abréviation de string, qui veut dire chaîne en français.

  1. >>> a = "hello world !"
  2. >>> type(a)
  3. <class 'str'>
  4. >>> b="1+2"
  5. >>> type(b)
  6. <class 'str'>
  7. >>> b
  8. '1+2'

Télécharger

Le type list (liste)
Dans Python, on peut définir une liste comme une collection d’éléments séparés par des virgules, l’ensemble étant écrit entre crochets.

  1. >>> jour = ["lundi", "mardi", "mercredi", "jeudi", "vendredi","samedi","dimanche"]
  2. >>> type(jour)
  3. <class 'list'>
  4. >>> L=[x**2 for x in range(10)]
  5. >>> type(L)
  6. <class 'list'>
  7. >>> L
  8. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Télécharger

Fonctions

- identifier les entrées et les sorties d’une fonction ;
Prenons l’exemple de la loi de Bernoulli, on peut définir une fonction loi de Bernoulli de paramètre 0.7 :

  1. from random import random
  2. def bernoulli():
  3. if random()<0.7:
  4. return(1)
  5. else:
  6. return(0)
  7.  
  8. >>> bernoulli()
  9. 1
  10. >>> bernoulli()
  11. 0

Télécharger

Il n’y a pas d’entrée, et en sortie on obtient 1 si l’expérience est un succès, 0 sinon.
Si l’on veut définir une loi de Bernoulli de paramètre p (au lieu de 0.7), on prendra en entrée le paramètre p, la sortie étant la même que précédemment :

  1. from random import random
  2. def bernoulli(p):
  3. if random()<p:
  4. return(1)
  5. else:
  6. return(0)
  7.  
  8. >>> bernoulli(0.4)
  9. 1
  10. >>> bernoulli(0.8)
  11. 0

Télécharger

Si l’on veut répéter n fois l’expérience :

  1. from random import random
  2. def bernoulli(n,p):
  3. succes=0
  4. for i in range(n):
  5. if random()<p:
  6. succes+=1
  7. return succes
  8.  
  9. >>> bernoulli(100,0.8)
  10. 82

Télécharger

En entrée, on renseigne le nombre d’expériences n et la probabilité du succès p. En sortie, on récupère le nombre de succès.
- structurer un programme en ayant recours aux fonctions. (Ceci est illustré partout dans l’article, nous n’en dirons pas plus ...)
Commentaires
- L’accent est mis sur la programmation modulaire qui permet de découper une tâche complexe en tâches plus simples.
Prenons l’exemple du calcul de l’écart-type pour une liste de données, on peut programmer la fonction :

  1. from math import sqrt
  2. def ecarttype(Liste):
  3. N=len(Liste)
  4. E_X=sum(Liste)/N
  5. varX = 0
  6. for i in range(N):
  7. varX += (Liste[i]-E_X)**2
  8. varX=varX/N
  9. return sqrt(varX)
  10.  
  11. >>> ecarttype([x**2 for x in range(10)])
  12. 26.852374196707448

Télécharger

On peut aussi programmer les fonctions esperance et variance afin de les utiliser dans la fonction ecarttype et éventuellement de s’en servir par ailleurs :

  1. from math import sqrt
  2. def esperance(Liste):
  3. return sum(Liste)/len(Liste)
  4. def variance(Liste):
  5. E_X=esperance(Liste)
  6. N=len(Liste)
  7. varX = 0
  8. for i in range(N):
  9. varX += (Liste[i]-E_X)**2
  10. varX=varX/N
  11. return varX
  12. def ecarttype(Liste):
  13. return sqrt(variance(Liste))
  14.  
  15. ecarttype([x**2 for x in range(10)])

Télécharger

Listes

- générer une liste (en extension, par ajouts successifs, en compréhension) ;
Une liste est une séquence modifiable. Un élément d’une liste peut être de n’importe quel type.

  1. >>> L=[6,1,69]
  2. >>> type(L)
  3. <class 'list'>
  4. >>> L[2]=1969
  5. >>> L
  6. [6, 1, 1969]
  7. >>> liste=[L,7,11,67,"Marie",18.2]
  8. >>> liste
  9. [[6, 1, 1969], 7, 11, 67, 'Marie', 18.2]
  10. >>> [a,b]=[0,1]
  11. >>> a
  12. 0
  13. >>> [a,b]
  14. [0, 1]

Télécharger

La liste vide :

  1. >>> L = []
  2. >>> L
  3. []

Télécharger

Longueur d’une liste : fonction len

  1. >>> a = [0,1,2,3]
  2. >>> len(a)
  3. 4

Télécharger


- manipuler des éléments d’une liste (ajouter, supprimer...) et leurs indices ;
Concaténation et multiplication
On concatène avec + :

  1. >>> a=[1,2,3]
  2. >>> b=a+[4,5]
  3. >>> b
  4. [1, 2, 3, 4, 5]
  5. >>> [0,1,2]+["Marie","Mylène"]+[67,72]
  6. [0, 1, 2, 'Marie', 'Mylène', 67, 72]

Télécharger

On peut utiliser la concaténation pour insérer un terme à la fin de la liste, mais on préférera utiliser la méthode append :

  1. >>> L = ["Benjamin","Alain"]
  2. >>> L.append("Yves")
  3. >>> L
  4. ['Benjamin', 'Alain', 'Yves']

Télécharger

On multiplie avec * :

  1. >>> [1,2,3]*3
  2. [1, 2, 3, 1, 2, 3, 1, 2, 3]
  3. >>> [1,2]*3
  4. [1, 2, 1, 2, 1, 2]
  5. >>> 2*["Pile","Face"]
  6. ['Pile', 'Face', 'Pile', 'Face']

Télécharger

Convertir avec la fonction list
On peut convertir n’importe quel itérable en liste :

  1. >>> list("abcdef")
  2. ['a', 'b', 'c', 'd', 'e', 'f']
  3. >>> list(b"abcdef")
  4. [97, 98, 99, 100, 101, 102]
  5. >>> list((0,1,2,3,4,5))
  6. [0, 1, 2, 3, 4, 5]
  7. >>> list(range(10))
  8. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  9. >>> list(range(5,9))
  10. [5, 6, 7, 8]

Télécharger

Indexing et slicing
Les listes sont des séquences, elles sont donc indexables (les items sont repérés par un indice) et sliceables (on peut en extraire des tranches grâce à des plages d’indices). Comme d’habitude, l’indice du premier item est zéro :

  1. >>> a=[42, 43, 45, 47]
  2. >>> a[2]
  3. 45
  4. >>> a[2]=12
  5. >>> a
  6. [42, 43, 12, 47]

Télécharger

Indices négatifs : Python numérote le dernier item avec -1, l’avant-dernier avec -2, et ainsi de suite :

  1. >>> a=[42, 43, 45, 47]
  2. >>> a[-1]
  3. 47
  4. >>> a[-2]
  5. 45

Télécharger

Si on est obligé d’initialiser les termes dans le désordre, on commencera par créer une liste triviale.
Supposons par exemple qu’on veuille L de longueur 10, on écrira :

  1. >>> L=[None]*10
  2. >>> L[5]=12
  3. >>> L
  4. [None, None, None, None, None, 12, None, None, None, None]

Télécharger

sans déclencher d’erreur.
Un peu de slicing :

  1. >>> a=[0,1,2,3,4,5,6,7,8,9]
  2. >>> a[3:7]
  3. [3, 4, 5, 6]
  4. >>> a[3:3]
  5. []
  6. >>> a[5:]
  7. [5, 6, 7, 8, 9]
  8. >>> a[:5]
  9. [0, 1, 2, 3, 4]
  10. >>> a[-3:-1]
  11. [7, 8]
  12. >>> a[-5:]
  13. [5, 6, 7, 8, 9]
  14. >>> a[:]
  15. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Télécharger

On peut faire du slicing avec un pas (positif ou négatif) :

  1. >>> a[2:20:3]
  2. [2, 5, 8]
  3. >>> a[::-1]
  4. [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
  5. >>> a[20:2:-2]
  6. [9, 7, 5, 3]

Télécharger

Remplacer une tranche par une autre
Dans une liste, on peut remplacer une tranche par une autre (il s’agit d’une mutation) :

  1. >>> L=list(range(15))
  2. >>> L[2:5]=5*[0]
  3. >>> L
  4. [0, 1, 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

Télécharger

On peut utiliser ce procédé pour changer un terme :

  1. >>> L=list(range(15))
  2. >>> L[3:4]=[7]
  3. >>> L
  4. [0, 1, 2, 7, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

Télécharger

On peut utiliser cette méthode pour supprimer une tranche :

  1. >>> L[2:5]=[]
  2. >>> L
  3. [0, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

Télécharger

On peut utiliser ce procédé pour supprimer un terme d’indice connu :

  1. >>> L[3:4]=[]
  2. >>> L
  3. [0, 1, 5, 7, 8, 9, 10, 11, 12, 13, 14]

Télécharger

On peut utiliser ce procédé pour insérer un élément où on veut :

  1. >>> L[5:5]=[25]
  2. >>> L
  3. [0, 1, 5, 7, 8, 25, 9, 10, 11, 12, 13, 14]

Télécharger

On peut insérer une tranche :

  1. >>> L[5:5]=[1,1,1,1,1]
  2. >>> L
  3. [0, 1, 5, 7, 8, 1, 1, 1, 1, 1, 25, 9, 10, 11, 12, 13, 14]

Télécharger

Compréhension
En mathématiques (théorie des ensembles), l’axiome de compréhension est fondamental :
Axiome : Si E est un ensemble et P une propriété exprimée dans le langage de la théorie des ensembles, alors $\left\{x \in E | P\right\}$ est un ensemble.
Il est très courant en mathématiques de définir des ensembles en compréhension. L’ensemble des nombres pairs, par exemple est l’ensemble $\left\{n \in \mathbb{Z} | n\equiv 0 [2] \right\}$.
On peut avec Python définir des listes en compréhension (on dit aussi en intension avec un s) :

  1. >>> X=[1,5,7,12]
  2. >>> Y=[x**2 for x in X]
  3. >>> Y
  4. [1, 25, 49, 144]

Télécharger

Y est la liste des carrés des nombres appartenant à X. On peut même ajouter une condition :

  1. >>> Y=[x**2 for x in X if x**2<30]
  2. >>> Y
  3. [1, 25]
  4. >>> Y=[x**2 for x in X if x<10]
  5. >>> Y
  6. [1, 25, 49]

Télécharger

On peut redéfinir X à partir de X directement :

  1. >>> X=[1,5,7,12]
  2. >>> X=[x**2 for x in X]
  3. >>> X
  4. [1, 25, 49, 144]

Télécharger

On peut imbriquer des listes en compréhension :

  1. >>> L = [[k for k in range(m)] for m in range(6)]
  2. >>> L
  3. [[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4]]

Télécharger

Fusionner
Soit L une liste de listes. On peut récupérer les items des listes de L en une seule instruction :

  1. >>> L = [[k for k in range(m)] for m in range(1,6)]
  2. >>> L
  3. [[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4]]
  4. >>> fusion=[x for SL in L for x in SL]
  5. >>> fusion
  6. [0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4]

Télécharger

On peut utiliser cette technique pour effectuer des produits de listes :

  1. >>> valeur = [1,7,8,9,10,"Valet","Dame","Roi"]
  2. >>> couleur = ["Coeur","Carreau","Pique","Trèfle"]
  3. >>> jeu = [(n,c) for n in valeur for c in couleur]
  4. >>> jeu
  5. [(1, 'Coeur'), (1, 'Carreau'), (1, 'Pique'), (1, 'Trèfle'), (7, 'Coeur'), (7, 'Carreau'), (7, 'Pique'),
  6. (7, 'Trèfle'), (8, 'Coeur'), (8, 'Carreau'), (8, 'Pique'), (8, 'Trèfle'), (9, 'Coeur'), (9, 'Carreau'),
  7. (9, 'Pique'), (9, 'Trèfle'), (10, 'Coeur'), (10, 'Carreau'), (10, 'Pique'), (10, 'Trèfle'), ('Valet',
  8. 'Coeur'), ('Valet', 'Carreau'), ('Valet', 'Pique'), ('Valet', 'Trèfle'), ('Dame', 'Coeur'),
  9. ('Dame', 'Carreau'), ('Dame', 'Pique'), ('Dame', 'Trèfle'), ('Roi', 'Coeur'), ('Roi', 'Carreau'),
  10. ('Roi', 'Pique'), ('Roi', 'Trèfle')]
  11. >>> (10,"Trèfle") in jeu
  12. True

Télécharger

Trier avec sort ou sorted (arguments reverse, key)
La fonction sorted et la méthode sort font la même chose : elles trient les items dans l’ordre croissant (par défaut). La fonction sorted prend n’importe quel itérable et retourne les items dans l’ordre, sous forme de liste :

  1. >>> L=[7,12,3,2]
  2. >>> sorted(L)
  3. [2, 3, 7, 12]
  4. >>> L
  5. [7, 12, 3, 2]

Télécharger

La méthode sort s’applique à une liste et modifie cette liste :

  1. >>> L.sort()
  2. >>> L
  3. [2, 3, 7, 12]

Télécharger

Les deux, sort et sorted, acceptent les arguments reverse et key. L’argument reverse permet de trier dans l’ordre décroissant :

  1. >>> sorted([7,12,3,2],reverse=True)
  2. [12, 7, 3, 2]

Télécharger

L’argument key permet de choisir la fonction avec laquelle on fera le tri. Si on veut trier selon la valeur absolue, on fera :

  1. >>> sorted([-13,15,-2,6,-6],key=abs)
  2. [-2, 6, -6, -13, 15]

Télécharger

Très pratique avec des données complexes :

  1. >>> def f(t):
  2. return t[1]
  3. >>> L=[["Marie",21],["Mylène",17],["Fred",24],["Denis",23]]
  4. >>> sorted(L,key=f)
  5. [['Mylène', 17], ['Marie', 21], ['Denis', 23], ['Fred', 24]]

Télécharger

Instruction del (mot réservé)
Pour effacer un item selon son rang, ou une plage d’items :

  1. >>> L=[7,12,3,2]
  2. >>> del L[2]
  3. >>> L
  4. [7, 12, 2]

Télécharger

Une autre syntaxe :

  1. >>> del(L[2])

On peut utiliser del sur une plage d’indices :

  1. >>> L=list(range(11))
  2. >>> del L[2:5]
  3. >>> L
  4. [0, 1, 5, 6, 7, 8, 9, 10]
  5. >>> L=list(range(21))
  6. >>> L
  7. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
  8. >>> del L[::3]
  9. >>> L
  10. [1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20]

Télécharger

Méthode index
Pour trouver l’indice d’un terme :

  1. >>> L=[0, 1, 6, 7, 8, 9, 10, 11, 12, 5, 6, 7, 8, 9, 10]
  2. >>> L.index(6)
  3. 2

Télécharger

C’est l’index de la première occurrence du terme qui est renvoyé, si l’on veut l’index de la seconde occurrence, on peut démarrer la recherche plus loin :

  1. >>> L.index(6,3)
  2. 10

Télécharger

Méthode count
Pour compter les occurrences d’un item :

  1. >>> L = [1,2,1,1,1,1,2,1,2]
  2. >>> L.count(2)
  3. 3
  4. >>> L.count(3)
  5. 0

Télécharger

Méthode remove
Pour supprimer une occurrence (ne supprime que la première occurrence) :

  1. >>> L = [1,10,56,23,897,56,1000]
  2. >>> L.remove(56)
  3. >>> L
  4. [1, 10, 23, 897, 56, 1000]
  5. >>> L.remove(100000)
  6. Traceback (most recent call last):
  7. File "<pyshell#165>", line 1, in <module>
  8. L.remove(100000)
  9. ValueError: list.remove(x): x not in list

Télécharger

Méthode append
Pour insérer un terme à la fin :

  1. >>> L = [1,10,56,23,897,56,1000]
  2. >>> L.append(1945)
  3. >>> L
  4. [1, 10, 56, 23, 897, 56, 1000, 1945]

Télécharger

Méthode insert
Pour insérer un terme où on veut :

  1. >>> L.insert(3,666)
  2. >>> L
  3. [1, 10, 56, 666, 23, 897, 56, 1000, 1945]

Télécharger

Méthode extend
Pour étendre une liste par concaténation :

  1. >>> LL=[456,567]
  2. >>> L.extend(LL)
  3. >>> L
  4. [1, 10, 56, 666, 23, 897, 56, 1000, 1945, 456, 567]

Télécharger

Méthode pop
Supprime le dernier terme et le retourne :

  1. >>> L.pop()
  2. 567
  3. >>> L
  4. [1, 10, 56, 666, 23, 897, 56, 1000, 1945, 456]

Télécharger

Fonction max
Retourne le plus grand élément :

  1. >>> max(L)
  2. 1945

Télécharger

Fonction min
Retourne le plus petit élément :

  1. >>> min(L)
  2. 1

Télécharger

Méthode copy
Pour copier une liste dans une autre :

  1. >>> LL=L.copy()
  2. >>> LL
  3. [1, 10, 56, 666, 23, 897, 56, 1000, 1945, 456]
  4. >>> LL==L
  5. True
  6. >>> LL is L
  7. False

Télécharger

Méthode clear
Pour effacer le contenu d’une liste :

  1. >>> L.clear()
  2. >>> L
  3. []

Télécharger


- itérer sur les éléments d’une liste.
Le type list est itérable
On peut itérer une liste :

  1. >>> for k in [1,2,3]:
  2. print(k,end=" ")
  3. 1 2 3

Télécharger

Les listes supportent les tests x in list et x not in list.

  1. >>> solide_platon=["Tétraèdre","Hexaèdre","Octaèdre","Dodécaèdre","Icosaèdre"]
  2. >>> "polyèdre" in solide_platon
  3. False

Télécharger

Commentaires
- La génération des listes en compréhension et en extension est mise en lien avec la notion d’ensemble. Les conditions apparaissant dans les listes définies en compréhension permettent de travailler la logique.
- Afin d’éviter des confusions, il est recommandé de se limiter aux listes sans présenter d’autres types de collections.

Sélection de données

- traiter un fichier contenant des données réelles pour en extraire de l’information et l’analyser ;
Nous utiliserons un gros fichier de données issu du site de l’INSEE, sur les communes de France métropolitaine et de Corse, débarrassé des données incomplètes (pour les DOM-TOM) :

Comma Separated Values - 2.3 Mo
Données sur les villes de France (Métropolitaine et Corse)

Nous traiterons ce fichier avec le module pandas qui est une librairie Python spécialisée dans l’analyse des données. Pour ma part, je l’utilise dans Spyder, mais cela est un détail à régler de votre côté ... Un objet de type "data frame" permet de réaliser de nombreuses opérations de filtrage, prétraitements, etc., préalables à la modélisation statistique.
Dans Spyder, on crée un fichier Python :

  1. import matplotlib as plt
  2. import pandas
  3. data=pandas.read_csv("villes_virgule.csv",sep=",")
  4. pandas.options.display.max_rows = 10 #On fait le choix de n'afficher que 10 lignes dans la console

Télécharger

On obtient dans la console un extrait des données qui sont enregistrées dans 36568 lignes et 12 colonnes, des "..." indiquent les "trous" présents dans cet affichage :

  1. In[63]:data
  2. Out[63]:
  3. dep nom cp ... lat alt_min alt_max
  4. 0 1 Ambérieu-en-Bugey 1500 ... 45.9500 237 753
  5. 1 1 Ambérieux-en-Dombes 1330 ... 46.0000 265 302
  6. 2 1 Ambléon 1300 ... 45.7500 330 940
  7. 3 1 Ambronay 1500 ... 46.0000 225 765
  8. 4 1 Ambutrix 1500 ... 45.9333 237 370
  9. .. ... ... ... ... ... ...
  10. 36563 2B Vivario 20219 ... 42.1731 400 2390
  11. 36564 2B Volpajola 20290 ... 42.5262 45 1231
  12. 36565 2B Zalana 20272 ... 42.2606 193 847
  13. 36566 2B Zilia 20214 ... 42.5303 172 1935
  14. 36567 2B Zuani 20272 ... 42.2714 411 1013
  15.  
  16. [36568 rows x 12 columns]

Télécharger

Par rapport au fichier original, la colonne des index des lignes a été rajoutée à gauche.
Il est possible d’afficher toutes les données grâce à l’explorateur de variables :

Structure DataFrame
Une matrice DataFrame correspond à une matrice individus-variables où les lignes correspondent à des observations, les colonnes à des attributs décrivant les individus. Concernant notre fichier "villes_virgule.csv" : la première ligne correspond aux noms des champs (des variables) ; à partir de la seconde ligne, nous disposons des valeurs pour chaque enregistrement (individu, ici une commune). Dans ce qui suit, nous chargeons le fichier de données et nous procédons à quelques vérifications.
Si l’on demande le type de data :

  1. print(type(data))
  2. <class 'pandas.core.frame.DataFrame'>

Télécharger

Voyons maintenant l’architecture de la structure DataFrame :

  1. print(data.shape)
  2. (36568, 12)

Télécharger

La ligne d’en-tête et la colonne d’index ne sont pas comptées.
Pour afficher l’en-tête de toutes les colonnes :

  1. print(data.columns)
  2. Index(['dep', 'nom', 'cp', 'nb_hab_2010', 'nb_hab_1999', 'nb_hab_2012', 'dens',
  3. 'surf', 'long', 'lat', 'alt_min', 'alt_max'],
  4. dtype='object')

Télécharger

On a donc le numéro du département, le nom de la commune, le code postal, le nombre d’habitants en 2010, le nombre d’habitants en 1999, le nombre d’habitants en 2012, la densité, la surface, la longitude, la latitude, l’altitude minimum et l’altitude maximum.
On peut récupérer les données statistiques de base pour chacune des colonnes :

  1. print(data.describe())
  2. nb_hab_2010 nb_hab_1999 ... alt_min alt_max
  3. count 3.656800e+04 3.656800e+04 ... 36568.000000 36568.000000
  4. mean 1.716628e+03 1.598173e+03 ... 193.157569 391.109166
  5. std 1.470343e+04 1.393150e+04 ... 194.694120 449.305955
  6. min 0.000000e+00 0.000000e+00 ... -5.000000 2.000000
  7. 25% 1.940000e+02 1.750000e+02 ... 62.000000 140.000000
  8. 50% 4.270000e+02 3.795000e+02 ... 138.000000 236.000000
  9. 75% 1.050000e+03 9.252500e+02 ... 253.000000 435.000000
  10. max 2.243833e+06 2.125851e+06 ... 1785.000000 4807.000000
  11. [8 rows x 9 columns]

Télécharger

Certaines des données ont plus ou moins d’intérêt selon le contexte, ici par exemple count correspond au nombre de données pour chaque colonne c’est-à-dire 36568 ...
On peut alors demander plus précisément les données pour une colonne précise :

  1. print(data["dens"].describe())
  2. count 36568.000000
  3. mean 153.984112
  4. std 703.669064
  5. min 0.000000
  6. 25% 18.000000
  7. 50% 39.000000
  8. 75% 90.000000
  9. max 26660.000000
  10. Name: dens, dtype: float64

Télécharger

Si l’on demande le calcul explicite de la moyenne :

  1. print(data["nb_hab_2010"].mean())
  2. 1716.6284456355284

Télécharger

Ou la population totale en 2010 :

  1. sum(data["nb_hab_2010"])
  2. Out[75]: 62773669

Télécharger

Le nombre de communes par département :

  1. print(data['dep'].value_counts())
  2. 62 895
  3. 2 816
  4. 80 782
  5. 76 745
  6. 57 730
  7. ...
  8. 90 102
  9. 94 47
  10. 93 40
  11. 92 36
  12. 75 1
  13. Name: dep, Length: 96, dtype: int64

Télécharger

data["dens"] est une liste, on peut donc lui appliquer toutes les méthodes des listes :

  1. data["dens"][0]
  2. Out[80]: 562
  3.  
  4. data["dens"][0:3]
  5. Out[81]:
  6. 0 562
  7. 1 101
  8. 2 19
  9. Name: dens, dtype: int64
  10.  
  11. data.dens[0:3]
  12. Out[82]:
  13. 0 562
  14. 1 101
  15. 2 19
  16. Name: dens, dtype: int64
  17. data["dens"].sort_values()
  18. Out[84]:
  19. 11593 0
  20. 22300 0
  21. 21144 0
  22. 3800 0
  23. 1577 0
  24.  
  25. 35923 23476
  26. 36009 24343
  27. 36021 25377
  28. 35952 25778
  29. 35919 26660
  30. Name: dens, Length: 36568, dtype: int64

Télécharger

On peut accéder aux valeurs du DataFrame via des indices ou plages d’indice. La structure se comporte alors comme une matrice. La cellule en haut et à gauche est de coordonnées (0,0). Il y a différentes manières de le faire, l’utilisation de .iloc[,] constitue une des solutions les plus simples. N’oublions pas que Shape permet d’obtenir les dimensions (lignes et colonnes) du DataFrame :

  1. print(data.iloc[0,0])
  2. 1
  3. print(data.iloc[5,8])
  4. 5.65
  5. print(data.iloc[-1,0])
  6. 2B
  7. print(data.iloc[data.shape[0]-1,0])
  8. 2B
  9. print(data.iloc[0:5,:])
  10. dep nom cp ... lat alt_min alt_max
  11. 0 1 Ambérieu-en-Bugey 1500 ... 45.9500 237 753
  12. 1 1 Ambérieux-en-Dombes 1330 ... 46.0000 265 302
  13. 2 1 Ambléon 1300 ... 45.7500 330 940
  14. 3 1 Ambronay 1500 ... 46.0000 225 765
  15. 4 1 Ambutrix 1500 ... 45.9333 237 370
  16. [5 rows x 12 columns]
  17. print(data.iloc[0:5,0:2])
  18. dep nom
  19. 0 1 Ambérieu-en-Bugey
  20. 1 1 Ambérieux-en-Dombes
  21. 2 1 Ambléon
  22. 3 1 Ambronay
  23. 4 1 Ambutrix
  24. print(data.iloc[0:5,[0,2,4]])
  25. dep cp nb_hab_1999
  26. 0 1 1500 11432
  27. 1 1 1330 1407
  28. 2 1 1300 86
  29. 3 1 1500 2144
  30. 4 1 1500 586

Télécharger

Nous pouvons isoler les sous-ensembles d’observations répondant à des critères définis sur les champs. Nous utiliserons préférentiellement la méthode .loc[,] dans ce cadre. Par exemple si l’on veut toutes les données correspondant au code postal 34400 :

  1. print(data.loc[data['cp']=="34400",:])
  2. dep nom cp ... lat alt_min alt_max
  3. 13262 34 Lunel 34400 ... 43.6833 2 53
  4. 13263 34 Lunel-Viel 34400 ... 43.6833 6 50
  5. 13359 34 Saint-Christol 34400 ... 43.7333 24 92
  6. 13384 34 Saint-Just 34400 ... 43.6500 2 9
  7. 13391 34 Saint-Nazaire-de-Pézan 34400 ... 43.6333 0 5
  8. 13399 34 Saint-Sériès 34400 ... 43.7333 14 68
  9. 13405 34 Saturargues 34400 ... 43.7167 16 68
  10. 13437 34 Vérargues 34400 ... 43.7167 15 65
  11. 13447 34 Villetelle 34400 ... 43.7333 10 67
  12. [9 rows x 12 columns]

Télécharger

Si l’on veut les communes du Nord de l’Hérault :

  1. print(data.loc[(data['dep']=="34") & (data['lat'] >43.9),:])
  2. dep nom cp ... lat alt_min alt_max
  3. 13112 34 Agonès 34190 ... 43.9167 119 323
  4. 13169 34 Cazilhac 34190 ... 43.9250 132 523
  5. 13211 34 Ganges 34190 ... 43.9333 138 540
  6. 13235 34 Laroque 34190 ... 43.9167 124 490
  7. 13288 34 Montoulieu 34190 ... 43.9333 159 522
  8. 13291 34 Moulès-et-Baucels 34190 ... 43.9500 156 727
  9. [6 rows x 12 columns]

Télécharger

pour visualiser l’évolution démographique des communes Héraultaises de plus de 10000 habitants en 1999 :

  1. colonnes = ['nom','nb_hab_1999','nb_hab_2010','nb_hab_2012']
  2. print(data.loc[(data['dep'] =="34") & (data['nb_hab_1999'] >10000),colonnes])
  3. nom nb_hab_1999 nb_hab_2010 nb_hab_2012
  4. 13110 Agde 20066 24567 22500
  5. 13139 Béziers 69359 70955 71700
  6. 13161 Castelnau-le-Lez 14208 14948 15000
  7. 13208 Frontignan 19130 22526 23200
  8. 13236 Lattes 13760 15927 16300
  9. 13262 Lunel 22346 25277 24400
  10. 13271 Mauguio 14846 16307 15800
  11. 13289 Montpellier 225511 257351 253000
  12. 13412 Sète 39579 42774 42800

Télécharger


- réaliser un tableau croisé de données sur deux critères à partir de données brutes.

On utilisera un second fichier, plus approprié, qui répertorie, selon leur ville de résidence, la LV2 étudiée par des lycéens :

Comma Separated Values - 1.4 ko
LV2 étudiée
  1. import matplotlib as plt
  2. import pandas
  3. data=pandas.read_csv("LV2.csv",sep=",")
  4. pandas.options.display.max_rows = 10
  5.  
  6. data
  7. Out[6]:
  8. LV2 ville
  9. 0 ANG Saint-Just
  10. 1 ITA Lansargues
  11. 2 ITA Saint-Just
  12. 3 ITA Lunel-Viel
  13. 4 ANG Lansargues
  14. .. ... ...
  15. 104 ITA Lunel
  16. 105 ALL Lunel
  17. 106 ANG Lunel
  18. 107 ITA Lansargues
  19. 108 ITA Lansargues
  20. [109 rows x 2 columns]

Télécharger

On peut alors calculer les effectifs et les fréquences :

  1. data["LV2"].value_counts()
  2. Out[2]:
  3. ANG 33
  4. ITA 33
  5. ALL 23
  6. ESP 20
  7. Name: LV2, dtype: int64
  8.  
  9. data["LV2"].value_counts(normalize=True)
  10. Out[3]:
  11. ANG 0.302752
  12. ITA 0.302752
  13. ALL 0.211009
  14. ESP 0.183486
  15. Name: LV2, dtype: float64

Télécharger

Et réaliser le tri croisé :

  1. pandas.crosstab(data["LV2"],data["ville"])
  2. Out[5]:
  3. ville Lansargues Lunel Lunel-Viel Saint-Just
  4. LV2
  5. ALL 5 10 3 5
  6. ANG 7 12 8 6
  7. ESP 4 6 6 4
  8. ITA 9 11 7 6

Télécharger

Ou avec la métode pivot_table(), qui donne exactement la même chose :

  1. data.pivot_table(index="LV2",columns="ville",aggfunc=len)

Suites numériques

Calculer un terme de rang donné d’une suite, une somme finie de termes.

Le calcul d’un terme de rang donné d’une suite définie de manière explicite, c’est-à-dire à l’aide d’une fonction de n est quelque chose de très simple :

  1. def u(n):
  2. return 3*n+1

Télécharger

Si l’on veut simplement un terme de rang donné, il suffit d’utiliser la fonction u :

  1. >>> u(5)
  2. 16

Télécharger

Regardons maintenant du côté des suites définies par récurrence. Prenons le cas d’une suite définie par $u_{n+1} = f(u_n)$ et de premier terme $u_{p}$ :

  1. def f(x):
  2. return 3*x+1
  3. def suite_recurrente(f,debut,fin,u_p):
  4. u=u_p
  5. for i in range(debut,fin):
  6. u=f(u)
  7. return u

Télécharger

Après avoir défini la fonction $f$, qui calcule $u_{n+1}$ en fonction de $u_{n}$, on calcule à l’aide d’une boucle les termes d’indice compris entre début+1 et fin. Si l’on veut $u_{12}$ :

  1. >>> suite_recurrente(f,0,12,2)
  2. 1328602

Télécharger

Étant donné que les suites arithmétiques et géométriques apparaissent dans le programme, il semble légitime de s’y intéresser particulièrement. On peut bien sûr utiliser la fonction suite_recurrente() (l’expression explicite de ces suites est au programme de Terminale) précédentes, il suffit d’écrire la relation de récurrence adéquate. Sinon, il est possible aussi de créer un outil spécifique qui prendrait en paramètres les rangs de début et de fin ainsi que le terme initial et la raison.

  1. def suite_geometrique_recurrence(debut,fin,u_p,raison):
  2. u=u_p
  3. for i in range(debut,fin):
  4. u*=raison
  5. return u
  6. def suite_arithmetique_recurrence(debut,fin,u_p,raison):
  7. u=u_p
  8. for i in range(debut,fin):
  9. u+=raison
  10. return u

Télécharger

Utilisation :

  1. >>> suite_arithmetique_recurrence(0,10,2,0.9)
  2. 11.000000000000002
  3. >>> suite_geometrique_recurrence(0,10,2,0.9)
  4. 0.6973568802000003

Télécharger

A noter les petites différences avec les résultats attendus de l’ordre de $10^{-15}$ dues à la gestion des nombres décimaux (flottants) dans Python. Cela peut se régler en utilisant la fonction round().
Si la suite est définie de manière explicite et que l’on veut la somme des termes de rang compris entre debut et fin :

  1. def u(n):
  2. return 3*n+1
  3. def somme_explicite(debut,fin):
  4. s=0
  5. for i in range(debut,fin+1):
  6. s=s+u(i)
  7. return s

Télécharger

Utilisation :

  1. >>> somme_explicite(5,9)
  2. 110

Télécharger

Si la suite est définie de manière récurrente et que l’on veut la somme des termes de rang compris entre debut et fin avec $u_{debut} = u_p$ :

  1. def f(x):
  2. return 3*x+1
  3. def somme_recurrente(debut,fin,u_p):
  4. s=u_p
  5. u=u_p
  6. for i in range(debut,fin):
  7. u=f(u)
  8. s=s+u
  9. return s

Télécharger

Utilisation :

  1. >>> somme_recurrente(3,7,5)
  2. 663

Télécharger

Déterminer une liste de termes d’une suite et les représenter.

Pour une suite déterminée de manière explicite :

  1. import matplotlib.pyplot as plt
  2. def u(n):
  3. return 0.2*n**2-1.2*n+1.6
  4. def graphe(u,debut,fin):
  5. for i in range(debut,fin):
  6. plt.scatter(i,u(i),c="red",marker='x')
  7. plt.grid()
  8. plt.show()

Télécharger

Taper dans la console :

  1. >>> graphe(u,0,12)
  2. [1.6, 0.6, 0, -0.2, 0, 0.6, 1.6, 3.0, 4.8, 7.0, 9.6, 12.6]

Télécharger


Pour une suite déterminée de manière récurrente :

  1. import matplotlib.pyplot as plt
  2. def u(n):
  3. return 0.2*n**2-1.2*n+1.6
  4. def suite_recurrente(u,debut,fin,u_p):
  5. liste_x=[debut]
  6. liste_y=[u_p]
  7. for i in range(debut,fin):
  8. liste_x.append(i+1)
  9. liste_y.append(u(liste_y[i]))
  10. plt.scatter(liste_x,liste_y)
  11. plt.grid()
  12. plt.show()
  13. return liste_y

Télécharger

Taper dans la console :

  1. >>> suite_recurrente(u,0,25,3)
  2. [3, -0.200, 1.848, 0.065, 1.522, 0.237, 1.327, 0.360, 1.194, 0.452, 1.098, 0.523, 1.027, 0.579,
  3. 0.973, 0.622, 0.931, 0.656, 0.899, 0.683, 0.874, 0.704, 0.854, 0.721, 0.839, 0.734]

Télécharger

Déterminer le rang à partir duquel les termes d’une suite sont supérieurs ou inférieurs à un seuil donné, ou aux termes de même rang d’une autre suite

Pour une suite, définie de manière explicite, pour laquelle on cherche à partir de quel rang son terme devient supérieur à un seuil donné :

  1. def u(n):
  2. return 0.2*n**2-1.2*n+1.6
  3. def seuil(u,debut,s):
  4. u_n=u(debut)
  5. compteur=debut
  6. while u_n<s:
  7. compteur+=1
  8. u_n=u(compteur)
  9. return u_n,compteur

Télécharger

utilisation :

  1. >>> seuil(u,0,1000)
  2. (1008.0, 74)

Télécharger

Le seuil de 1000 est dépassé au rang 74 avec $u_{74}=1008$.

Pour une suite, définie par récurrence, pour laquelle on cherche à partir de quel rang son terme devient supérieur à un seuil donné :

  1. def u(n):
  2. return 3*n+1
  3. def seuil(u,debut,u_p,s):
  4. compteur=debut
  5. while u_p<s:
  6. compteur+=1
  7. u_p=u(u_p)
  8. return u_p,compteur

Télécharger

utilisation :

  1. >>> seuil(u,1,5,1000)
  2. (1336, 6)

Télécharger

Le seuil de 1000 est dépassé au rang 6 avec $u_{6}=1336$.

Pour une suite, définie de manière explicite, pour laquelle on cherche à partir de quel rang son terme devient inférieur à un seuil donné :

  1. def u(n):
  2. return -0.2*n**2+1.2*n+1000
  3. def seuil(u,debut,s):
  4. u_n=u(debut)
  5. compteur=debut
  6. while u_n>s:
  7. compteur+=1
  8. u_n=u(compteur)
  9. return u_n,compteur

Télécharger

utilisation :

  1. >>> seuil(u,0,500)
  2. (481.5999999999999, 54)

Télécharger

La suite passe sous le seuil de 500 au rang 54 avec $u_{54}=481.6$.

Pour une suite, définie par récurrence, pour laquelle on cherche à partir de quel rang son terme devient inférieur à un seuil donné :

  1. def u(n):
  2. return 1.03*n-250
  3. def seuil(u,debut,u_p,s):
  4. compteur=debut
  5. while u_p>s:
  6. compteur+=1
  7. u_p=u(u_p)
  8. return u_p,compteur

Télécharger

utilisation :

  1. >>> seuil(u,1,2000,250)
  2. (69.7698357481176, 10)

Télécharger

La suite passe sous le seuil de 250 au rang 10 avec $u_{11}\approx 69.77$.

Déterminer le rang à partir duquel les termes d’une suite sont supérieurs aux termes de même rang d’une autre suite avec deux suites définies par récurrence :

  1. def u(n):
  2. return n+400
  3. def v(n):
  4. return 1.025*n
  5. def seuil(u,v,debut,u_p,v_p):
  6. compteur=debut
  7. while u_p>=v_p:
  8. compteur+=1
  9. u_p=u(u_p)
  10. v_p=v(v_p)
  11. return u_p,v_p,compteur

Télécharger

utilisation :

  1. >>> seuil(u,v,0,10000,10000)
  2. (24800, 24933.486986108404, 37)

Télécharger

Déterminer le rang à partir duquel les termes d’une suite sont supérieurs aux termes de même rang d’une autre suite avec deux suites définies de manière implicite :

  1. def u(n):
  2. return 10000+400*n
  3. def v(n):
  4. return 10000*1.025**n
  5. def seuil(u,v,debut):
  6. compteur=debut
  7. u_p,v_p=u(debut),v(debut)
  8. while u_p>=v_p:
  9. compteur+=1
  10. u_p=u(compteur)
  11. v_p=v(compteur)
  12. return u_p,v_p,compteur

Télécharger

utilisation :

  1. >>> seuil(u,v,0)
  2. (24800, 24933.4869861084, 37)

Télécharger

Fonctions de la variable réelle

Calculer une valeur approchée d’une solution d’une équation par balayage.

Cette méthode, classique, consiste, pour une fonction continue et monotone sur un intervalle [a ; b] dans lequel on sait trouver la solution de $f(x) = k$, à calculer $f(x)$, pour $x$ allant de a à b avec un pas de h, après avoir vérifié la croissance ou la décroissance de la fonction. Si f est croissante, "Tant Que" f(x) < k est vérifiée (On utilisera pour cela un While.), on calcule f(x). Dès que f(x) > k on arrête l’algorithme. Si f est décroissante, "Tant Que" f(x) > k est vérifiée, on calcule f(x). Dès que f(x) < k on arrête l’algorithme. On obtient un encadrement de longueur h de la solution
Il faut déterminer a et b, les bornes de l’intervalle dans lequel on va appliquer le balayage.
Fonction qui calcule cet encadrement, renvoyé dans un tuple, en fonction du nombre n de décimales souhaitées :
Cet algorithme détermine par balayage un encadrement de racine de 2 d’amplitude 10^(-n).

  1. def balayage(f,k,a,b,n):
  2. fa,fb=f(a),f(b)
  3. h=10**(-n)
  4. x=a
  5. if fa<fb:
  6. while f(x)<k:
  7. x=x+h
  8. else:
  9. while f(x)>k:
  10. x=x+h
  11. return (round(x-h,n),round(x,n))

Télécharger

Utilisation : Compiler le fichier puis dans la console :

  1. >> balayage(f,20,-3,-1,2)
  2. (-1.89, -1.88)
  3. >>> balayage(f,20,6,8,3)
  4. (6.887, 6.888)

Télécharger

Le round permet ici de corriger quelques erreurs d’affichage des flottants [1].
Il est à noter que cet algorithme est très long à donner une réponse si n>=9.
On peut donc chercher à l’optimiser, par exemple en utilisant une boucle for qui va faire la même chose que le programme précédent mais pour h allant de 10-1 à 10-n en réduisant l’intervalle [a ; b] à chaque boucle.
C’est beaucoup plus rapide, jusqu’à n=16 où ça bogue, parce que les flottants (décimaux) ne sont affichés qu’avec 16 chiffres après la virgule.

  1. def f(x):
  2. return x**2-5*x+7
  3. def balayage(f,k,a,b,n):
  4. fa,fb=f(a),f(b)
  5. for i in range(1,n+1):
  6. h=10**(-i)
  7. x=a
  8. if fa<fb:
  9. while f(x)<k:
  10. x=x+h
  11. else:
  12. while f(x)>k:
  13. x=x+h
  14. a=x-h
  15. return (round(x-h,n),round(x,n))

Télécharger

Croisement de deux variables catégorielles

À partir de deux listes représentant deux caractères d’individus, déterminer un sous-ensemble d’individus répondant à un critère (filtre, utilisation des ET, OU, NON).

Soit l’on se donne une telle liste soit on la génère aléatoirement, par exemple :

  1. from random import randint
  2. taille=[randint(160,190) for t in range(35)]
  3. distance_lycee=[randint(0,25) for d in range(35)]
  4. echantillon=[]
  5. for i in range(35):
  6. echantillon.append([taille[i],distance_lycee[i]])

Télécharger

On obtient par exemple :

  1. >>> echantillon
  2. [[165, 18], [180, 19], [174, 22], [181, 17], [184, 12], [180, 16], [172, 10], [169, 3],
  3. [168, 25], [183, 5], [181, 4], [188, 12], [188, 23], [179, 2], [160, 23], [181, 14],
  4. [183, 1], [170, 7], [172, 3], [182, 15], [161, 9], [167, 1], [164, 22], [189, 17],
  5. [173, 11], [181, 11], [164, 11], [168, 25], [163, 14], [165, 12], [188, 8], [183, 2],
  6. [174, 19], [188, 8], [179, 0]]

Télécharger

On peut alors déterminer différents sous-ensembles :

  1. >>> grands=[x for x in echantillon if x[0]>185]
  2. >>> grands
  3. [[188, 12], [188, 23], [189, 17], [188, 8], [188, 8]]
  4. >>> petits=[x for x in echantillon if x[0]<165]
  5. >>> petits
  6. [[160, 23], [161, 9], [164, 22], [164, 11], [163, 14]]
  7. >>> proches=[x for x in echantillon if x[1]<5]
  8. >>> proches
  9. [[169, 3], [181, 4], [179, 2], [183, 1], [172, 3], [167, 1], [183, 2], [179, 0]]
  10. >>> pas_trop_loin=[x for x in echantillon if x[1]>5 and x[1]<15]
  11. >>> pas_trop_loin
  12. [[184, 12], [172, 10], [188, 12], [181, 14], [170, 7], [161, 9], [173, 11], [181, 11],
  13. [164, 11], [163, 14], [165, 12], [188, 8], [188, 8]]
  14. >>> petits_ou_proches=[x for x in echantillon if x[0]<165 or x[1]<5]
  15. >>> petits_ou_proches
  16. [[169, 3], [181, 4], [179, 2], [160, 23], [183, 1], [172, 3], [161, 9], [167, 1],
  17. [164, 22], [164, 11], [163, 14], [183, 2], [179, 0]]
  18. >>> petits_ou_grands=[x for x in echantillon if not(165<x[0]<185)]
  19. >>> petits_ou_grands
  20. [[165, 18], [188, 12], [188, 23], [160, 23], [161, 9], [164, 22], [189, 17], [164, 11],
  21. [163, 14], [165, 12], [188, 8], [188, 8]]

Télécharger

Dresser le tableau croisé de deux variables catégorielles à partir du fichier des individus et calculer des fréquences conditionnelles ou marginales.

Sans le module Pandas
On peut partir de deux listes, ou d’une liste regroupant les deux listes, nous choisissons de générer cette liste aléatoirement dans le programme Python, en utilisant la méthode choice() pour tirer aléatoirement un élément d’une liste (ici dans les deux listes intitules), puis de traiter les données afin d’établir le tableau croisé :

  1. from random import choice
  2. def tableau_croise(intitules1,intitules2,n):
  3. echantillon=[]
  4. L1=len(intitules1)
  5. L2=len(intitules2)
  6. for i in range(n):
  7. echantillon.append([choice(intitules1),choice(intitules2)])
  8. a=[[0]*len(intitules2)]
  9. for i in range(L1-1):
  10. a+=[[0]*len(intitules2)]
  11. for k in range(n):
  12. i = intitules1.index(echantillon[k][0])
  13. j = intitules2.index(echantillon[k][1])
  14. a[i][j]+=1
  15. etiquettes=["Effectifs",intitules2[0],intitules2[1],intitules2[2],"Total"]
  16. ligne1=[intitules1[0],a[0][0],a[0][1],a[0][2],a[0][0]+a[0][1]+a[0][2]]
  17. ligne2=[intitules1[1],a[1][0],a[1][1],a[1][2],a[1][0]+a[1][1]+a[1][2]]
  18. ligne3=["Total",a[0][0]+a[1][0],a[0][1]+a[1][1],a[0][2]+a[1][2],n]
  19. tab=[etiquettes,ligne1,ligne2,ligne3]
  20. form="{0:15}{1:^10}{2:^10}{3:^10}{4:^10}" # ^ sert à centrer le texte. 10 est la largeur en nombre de caractères
  21. for val in tab:
  22. print(form.format(*val))

Télécharger

La méthode index() cherche un élément dans la liste et renvoie son index. En termes simples, la méthode index() trouve un élément donné dans une liste et renvoie sa position, ce qui nous permet de les compter et d’établir le tableau des effectifs.
A noter que l’on crée la matrice a=[0,0,...,0]...[0,0,...,0] avec :

  1. a=[[0]*len(intitules2)]
  2. for i in range(L1-1):
  3. a+=[[0]*len(intitules2)]

Télécharger

et non pas avec :

  1. a=[[0]*len(intitules2)]*len(intitules1)

Plutôt qu’un long discours l’explication est dans le code ci-dessous :

  1. >>> b=[[0,0,0],[0,0,0]]
  2. >>> b
  3. [[0, 0, 0], [0, 0, 0]]
  4. >>> b[1][2]=1
  5. >>> b
  6. [[0, 0, 0], [0, 0, 1]]
  7. >>> a=[[0]*3]*2
  8. >>> a
  9. [[0, 0, 0], [0, 0, 0]]
  10. >>> a[1][2]=1
  11. >>> a
  12. [[0, 0, 1], [0, 0, 1]]

Télécharger

Une petite mise en forme s’impose si l’on veut obtenir quelque chose de lisible (ceci n’a pas besoin d’être expliqué aux élèves, il s’agit de cosmétique ...).
Utilisation :

  1. >>> tableau_croise(["Célibataire","Marié"],["Collège","Lycée","Supérieur"],35)
  2. Effectifs Collège Lycée Supérieur Total
  3. Marié 4 9 9 22
  4. Célibataire 4 9 10 23
  5. Total 8 18 19 45

Télécharger

Pour obtenir les fréquences, on complète le code précédent avec :

  1. print("\n")
  2. etiquettes_f=["Fréquences",intitules2[0],intitules2[1],intitules2[2],"Total"]
  3. ligne1_f=[intitules1[0],round(a[0][0]/n,4),round(a[0][1]/n,4),round(a[0][2]/n,4),round((a[0][0]+a[0][1]+a[0][2])/n,4)]
  4. ligne2_f=[intitules1[1],round(a[1][0]/n,4),round(a[1][1]/n,4),round(a[1][2]/n,4),round((a[1][0]+a[1][1]+a[1][2])/n,4)]
  5. ligne3_f=["Total",round((a[0][0]+a[1][0])/n,4),round((a[0][1]+a[1][1])/n,4),round((a[0][2]+a[1][2])/n,4),1]
  6. tab_freq=[etiquettes_f,ligne1_f,ligne2_f,ligne3_f]
  7. for val in tab_freq:
  8. print(form.format(*val))

Télécharger

Pour obtenir :

  1. Fréquences Collège Lycée Supérieur Total
  2. Marié 0.0889 0.2 0.2 0.4889
  3. Célibataire 0.0889 0.2 0.2222 0.5111
  4. Total 0.1778 0.4 0.4222 1

Télécharger

On a alors dans les colonnes "Total" les fréquences marginales :
- 17,78% des individus ont un niveau Collège.
- 48,89% des individus sont Mariés.
Avec le module Pandas
Sinon, on peut traiter un fichier csv qui contient ces données avec le module pandas qui est une librairie Python spécialisée dans l’analyse des données. Pour ma part, je l’utilise dans Spyder, mais cela est un détail à régler de votre côté ... Un objet de type "data frame" permet de réaliser de nombreuses opérations de filtrage, prétraitements, etc., préalables à la modélisation statistique.
Dans Spyder, on crée un fichier Python :

  1. import pandas
  2. data=pandas.read_csv("statut_niveau.csv",sep="\t|,")
  3. pandas.options.display.max_rows = 10

Télécharger

qui ouvre un fichier statut_niveau.csv qui contient les données, le voici :

Comma Separated Values - 1.1 ko
Statut et niveau

On vérifie dans la console :

  1. data
  2. Out[33]:
  3. Statut Niveau
  4. 0 Célibataire Collège
  5. 1 Célibataire Lycée
  6. 2 Célibataire Collège
  7. 3 Célibataire Supérieur
  8. 4 Marié Supérieur
  9. .. ... ...
  10. 52 Marié Lycée
  11. 53 Marié Supérieur
  12. 54 Marié Lycée
  13. 55 Célibataire Supérieur
  14. 56 Célibataire Collège
  15. [57 rows x 2 columns]

Télécharger

Et on demande le tableau croisé :

  1. pandas.crosstab(data["Statut"],data["Niveau"])
  2. Out[34]:
  3. Niveau Collège Lycée Supérieur
  4. Statut
  5. Célibataire 13 6 7
  6. Marié 10 11 10

Télécharger

Avec les totaux par ligne et par colonne :

  1. pandas.crosstab(data["Statut"],data["Niveau"], margins=True)
  2. Out[75]:
  3. Niveau Collège Lycée Supérieur All
  4. Statut
  5. Célibataire 13 6 7 26
  6. Marié 10 11 10 31
  7. All 23 17 17 57

Télécharger

On peut obtenir le tableau des fréquences conditionnelles selon le niveau :

  1. pandas.crosstab(data["Statut"],data["Niveau"],normalize="index", margins=True)
  2. Out[41]:
  3. Niveau Collège Lycée Supérieur
  4. Statut
  5. Célibataire 0.500000 0.230769 0.269231
  6. Marié 0.322581 0.354839 0.322581
  7. All 0.403509 0.298246 0.298246

Télécharger

On lit ainsi que :
- "50% des individus Célibataires ont un niveau Collège." (fréquence conditionnelle)
- "35,48% des individus Mariés ont un niveau Lycée ." (fréquence conditionnelle)
- "40,35% desindividus ont un niveau Collège" (fréquence marginale)
On peut obtenir le tableau des fréquences conditionnelles selon le Statut :

  1. pandas.crosstab(data["Statut"],data["Niveau"], Normalize="columns", margins=True)
  2. Out[79]:
  3. Niveau Collège Lycée Supérieur All
  4. Statut
  5. Célibataire 0.565217 0.352941 0.411765 0.45614
  6. Marié 0.434783 0.647059 0.588235 0.54386

Télécharger

On lit ainsi que :
- "35,29% des individus ayant un niveau Lycée sont célibataires." (fréquence conditionnelle)
- "58,82% des individus ayant un niveau Supérieur sont mariés." (fréquence conditionnelle)
- "45,61% des individus sont célibataires." (fréquence marginale)
Et enfin le tableau des fréquences :

  1. pandas.crosstab(data["Statut"],data["Niveau"],normalize="all")
  2. Out[43]:
  3. Niveau Collège Lycée Supérieur
  4. Statut
  5. Célibataire 0.228070 0.105263 0.122807
  6. Marié 0.175439 0.192982 0.175439

Télécharger

Avec les totaux :

  1. pandas.crosstab(data["Statut"],data["Niveau"],normalize="all",margins=True)
  2. Out[80]:
  3. Niveau Collège Lycée Supérieur All
  4. Statut
  5. Célibataire 0.228070 0.105263 0.122807 0.45614
  6. Marié 0.175439 0.192982 0.175439 0.54386
  7. All 0.403509 0.298246 0.298246 1.00000

Télécharger

Où l’on retrouve les fréquences marginales dans la colonne et la ligne "All".

Si l’on s’intéresse à des données numériques assez nombreuses, il peut être intéressant de croiser ces données par classes d’intervalles, avec le fichier ci-dessous :

Comma Separated Values - 1.8 ko
taille et distance
  1. import pandas
  2. data=pandas.read_csv("taille_distance.csv",sep="\t|,")
  3. pandas.options.display.max_rows = 10

Télécharger

On demande alors dans la console :

  1. pandas.crosstab(pandas.cut(data["taille"], bins = [160, 170,180,190,200], include_lowest=True),
  2. ... pandas.cut(data["dist lycée"],bins=[0,10,20,30], include_lowest=True))
  3. Out[53]:
  4. dist lycée (-0.001, 10.0] (10.0, 20.0] (20.0, 30.0]
  5. taille
  6. (159.999, 170.0] 38 32 17
  7. (170.0, 180.0] 27 29 12
  8. (180.0, 190.0] 30 22 17
  9. (190.0, 200.0] 23 18 9

Télécharger

Variables aléatoires

Simuler des échantillons de taille n d’une loi de Bernoulli à partir d’un générateur de nombres aléatoires entre 0 et 1.

Le module random est un module qui regroupe des fonctions permettant de simuler le hasard. Parmi ces fonctions, la fonction random() donne un flottant au hasard dans l’intervalle [0 ; 1[. Soit p la probabilité du succès d’une expérience de Bernoulli.
On peut ainsi simuler une épreuve de Bernoulli :

  1. def bernoulli(p):
  2. if random()<p:
  3. return(1)
  4. else:
  5. return(0)

Télécharger

Utilisation :

  1. >>> bernoulli(0.8)
  2. 1

Télécharger

On peut alors répéter cette expérience n fois :

  1. def echantillon(n,p):
  2. L=[bernoulli(p) for i in range(n)]
  3. return L

Télécharger

Utilisation :

  1. >>> echantillon(25,0.6)
  2. [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1]

Télécharger

On peut alors calculer la fréquence du succès lors de N expériences d’un échantillon de taille n :

  1. def frequences(N,n,p):
  2. F=[sum(echantillon(n,p))/n for k in range(N)]
  3. return F

Télécharger

Utilisation :

  1. >>> frequences(500,100,0.7)
  2. [0.66, 0.65, 0.68, 0.8, 0.67, 0.71, 0.68, 0.6, 0.78, 0.72, 0.7, 0.68, 0.63, ...

Télécharger

Représenter par un histogramme ou par un nuage de points les fréquences observées des 1 dans N échantillons de taille n d’une loi de Bernoulli.

On peut illustrer graphiquement le résultat obtenu après avoir calculé la fréquence du succès lors de N expériences d’un échantillon de taille n (voir paragraphe précédent la fonction frequences(N,n,p) réutilisée ici) :
- par un histogramme :

  1. import matplotlib.pyplot as plt
  2. def histogramme(N,n,p):
  3. plt.grid()
  4. plt.hist(frequences(N,n,p),range=(p-0.25,p+0.25),edgecolor = 'grey')
  5. plt.xlabel("fréquences")
  6. plt.ylabel("effectifs")
  7. plt.title("histogramme")
  8. return plt.show()

Télécharger

Utilisation :

  1. >>> histogramme(1000,100,0.8)


- par un nuage de points :

  1. import matplotlib.pyplot as plt
  2. def nuage(N,n,p):
  3. plt.grid()
  4. plt.scatter(range(N),frequences(N,n,p),c="red",marker=".")
  5. plt.xlim([0,N])
  6. plt.ylim([0,1])
  7. return plt.show()

Télécharger

Utilisation :

  1. >>> nuage(2000,500,0.7)

Compter le nombre de valeurs situées dans un intervalle de la forme [p-ks ; p+ks] pour k∈1 ; 2 ; 3

Pour calculer l’écart-type :

  1. from math import sqrt
  2. def esperance(Liste):
  3. return sum(Liste)/len(Liste)
  4. def variance(Liste):
  5. E_X=esperance(Liste)
  6. N=len(Liste)
  7. varX = 0
  8. for i in range(N):
  9. varX += (Liste[i]-E_X)**2
  10. varX=varX/N
  11. return varX
  12. def ecarttype(Liste):
  13. return sqrt(variance(Liste))

Télécharger

Pour compter le nombre de valeurs situées dans un intervalle de la forme $[p-ks ; p+ks]$ pour $k\in\left\{1 ; 2 ; 3\right\}$ :

  1. def effectifs(F,p,k):
  2. s=ecarttype(F)
  3. a=p-k*s
  4. b=p+k*s
  5. i=0
  6. for x in F:
  7. if x>=a and x<=b:
  8. i=i+1
  9. return i

Télécharger

Utilisation :

  1. >>> effectifs(frequences(1000,100,0.7),0.7,1)
  2. 658
  3. >>> effectifs(frequences(1000,100,0.7),0.7,2)
  4. 961
  5. >>> effectifs(frequences(1000,100,0.7),0.7,3)
  6. 998

Télécharger

Et si l’on veut plutôt récupérer la fréquence de 1 dans ces intervalles :

  1. def pourcentages(F,N,p,k):
  2. s=ecarttype(F)
  3. a=p-k*s
  4. b=p+k*s
  5. i=0
  6. for x in F:
  7. if x>=a and x<=b:
  8. i=i+1
  9. return(100*i/N)

Télécharger

Utilisation (en utilisant la fonction fréquence vue deux paragraphes au-dessus) :

  1. >>> pourcentages(frequences(1000,100,0.7),1000,0.7,3)
  2. 99.7
  3. >>> pourcentages(frequences(1000,100,0.7),1000,0.7,2)
  4. 96.2
  5. >>> pourcentages(frequences(1000,100,0.7),1000,0.7,1)
  6. 68.5

Télécharger

On peut utiliser la fonction nuage(N,n,p) vue précédemment pour y rajouter les droites d’équations y =μ-kσ et y = μ +kσ pour illustrer cela :

  1. def nuage_ks(N,n,p,k):
  2. L=frequences(N,n,p)
  3. E_X=esperance(L)
  4. s=ecarttype(L)
  5. a=E_X-k*s
  6. b=E_X+k*s
  7. plt.plot([0,N],[a,a],"b-")
  8. plt.plot([0,N],[b,b],"b-")
  9. titre=("Nuage de points et droites d'équations y =μ-{0}σ et y = μ +{0}σ.".format(k,k))
  10. plt.suptitle(titre)
  11. nuage(N,n,p)
  12. return plt.show()

Télécharger

Utilisation :

  1. >>> nuage_ks(1000,100,0.7,2)
PNG - 31.4 ko
Bernoulli

Bibliographie


Réagir à cet article
Vous souhaitez compléter cet article pour un numéro futur, réagir à son contenu, demander des précisions à l'auteur ou au comité de rédaction...
À lire aussi ici
MathémaTICE est un projet
en collaboration avec
Suivre la vie du site Flux RSS 2.0  |  Espace de rédaction  |  Nous contacter  |  Site réalisé avec: SPIP  |  N° ISSN 2109-9197