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) :

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 :

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,0,0,5,5)
  2. (1.41421, 1.41422)

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 balayage2(f,k,a,b,n):
  2.     fa,fb=f(a),f(b)
  3.     for i in range(1,n+1):
  4.         h=10**(-i)
  5.         x=a
  6.         if fa<fb:
  7.             while f(x)<k:
  8.                 x=x+h
  9.         else:
  10.             while f(x)>k:
  11.                 x=x+h
  12.         a=x-h
  13.     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 :

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 :

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)
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