Mapytex/pymath/stat/dataset.py
2016-01-09 13:20:20 +03:00

381 lines
14 KiB
Python

#/usr/bin/env python
# -*- coding:Utf-8 -*-
#
#
# Ensemble de fonction rendant beaucoup plus pratique la résolution et l'élaboration des exercices de stat au lycée
#
#
from math import sqrt, ceil
class Dataset(list):
""" A dataset (a list) with statistics and latex rendering methods
>>> s = Dataset(range(100))
>>> s.sum()
4950
>>> s.mean()
49.5
>>> s.deviation()
83325.0
>>> s.variance()
833.25
>>> s.sd()
28.86607004772212
"""
def __init__(self, data = [], data_name = "Valeurs"):
"""
Create a numeric data set
:param data: values of the data set
:param data_name: name of the data set
"""
list.__init__(self, data)
self_name = data_name
def add_data(self, data):
"""Add datas to the data set
:param data: datas
"""
try:
self += data
except TypeError:
self += [data]
def effectif_total(self):
return len(self)
def sum(self):
return sum(self)
def mean(self):
return self.sum()/self.effectif_total()
def deviation(self):
""" Compute the deviation (not normalized) """
mean = self.mean()
return sum([(x - mean)**2 for x in self])
def variance(self):
return self.deviation()/self.effectif_total()
def sd(self):
""" Compute the standard deviation """
return sqrt(self.variance())
def quartiles(self):
"""
Calcul les quartiles de la série.
:return: un tuple avec (min, Q1, Me, Q3, Max)
>>> w = Dataset(range(12))
>>> w.quartiles()
(0, 2.5, 5.5, 8.5, 11)
"""
return (min(self) , self.quartile(1) , self.quartile(2) , self.quartile(3), max(self))
def quartile(self, quartile = 1):
"""
Calcul un quartile de la série.
:param quartile: quartile à calculer (par defaut 1 -> Q1)
:return: le quartile demandé
: Example:
>>> w = Dataset(range(12))
>>> w.quartile(1)
2.5
>>> w.quartile(2)
5.5
>>> w.quartile(3)
8.5
>>> w = Dataset(range(14))
>>> w.quartile(1)
3
>>> w.quartile(2)
6.5
>>> w.quartile(3)
10
"""
# -1 to match with list indexing
position = self.posi_quartile(quartile) - 1
if position.is_integer():
return (self[int(position)] + self[int(position)+1])/2
else:
return self[ceil(position)]
def posi_quartile(self, quartile = 1):
"""
Calcul la position du quartile
:param quartile: le quartile concerné
:return : la position du quartile (arondis à l'entier suppérieur, non arrondis)
"""
return quartile * self.effectif_total() / 4
# --------------------------
# Rendu latex
def moyenne_latex(self, val_cara = "x", eff_cara = "n", end_cara = "p", moy_cara= "\\bar{x}"):
"""
Renvoie le code latex pour afficher le calcul de la moyenne
:param val_cara: caractère représentant les valeurs (x par défaut)
:param eff_cara: caractère représentant les effectifs (n par défaut)
:param end_cara: caractère représentant le nombre de valeurs (p par défaut)
:param moy_cara: nom de la moyenne (\\bar{x} par défaut)
:return: le code latex pour afficher le calcul de la moyenne
"""
moy = self.moyenne()
latex = moy_cara + " &=& "
latex += "\\frac{{{x}_1 \\times {n}_1 + {x}_2 \\times {n}_2 + ... + {x}_{p} \\times {n}_{p}}}{{{n}_1 + {n}_2 + ... + {n}_p}} \\\\ \n".format(x = val_cara, n=eff_cara, p = end_cara)
latex += "\t &=& \\frac{"
for (i,v) in enumerate(self.valeurs):
latex += "{x:.2f} \\times {p:.2f} + ".format(x = v, p = self.effectifs[i])
latex = latex[:-2] # on enlève le + et l'espace de fin de calcul
latex += "}}{{{eff_tot}}}\\\\ \n".format(eff_tot = self.effectif_total)
latex += "\t &=& {moy:.2f}".format(moy=moy)
return latex
def variance_latex(self, val_cara = "x", eff_cara = "n", end_cara = "p", moy_cara= "\\bar{x}", var_cara = "V"):
"""
Renvoie le code latex pour afficher le calcul de la moyenne
:param val_cara: caractère représentant les valeurs (x par défaut)
:param eff_cara: caractère représentant les effectifs (n par défaut)
:param end_cara: caractère représentant le nombre de valeurs (p par défaut)
:param moy_cara: nom de la moyenne (\\bar{x} par défaut)
:param var_var: nom de la variance (V par défaut)
:return: le code latex pour afficher le calcul de la moyenne
"""
moy = self.moyenne()
var = self.variance()
latex = var_cara + " &=& "
latex += "\\frac{{ {n}_1 ({x}_1 - {moy})^2 + {n}_2 ({x}_2 - {moy})^2 + ... + {n}_{p} ({x}_{p} - {moy})^2}}{{{n}_1 + {n}_2 + ... + {n}_p}}\\\\ \n".format(x = val_cara, n=eff_cara, p = end_cara, moy = moy_cara)
latex += "\t &=& \\frac{ "
for (i,v) in enumerate(self.valeurs):
latex += "{p:.2f} ({x:.2f} - {moy:.2f})**2 + ".format(p = self.effectifs[i], x = v, moy = moy)
latex = latex[:-2] # on enlève le + et l'espace de fin de calcul
latex += "}}{{{eff_tot}}}\\\\ \n".format(eff_tot = self.effectif_total)
latex += "\t &=& {var:.2f}".format(var = var)
return latex
def ecart_type_latex(self, val_cara = "x", eff_cara = "n", end_cara = "p", moy_cara= "\\bar{x}", var_cara = "V", ecar_cara = "\\sigma"):
"""
Renvoie le code latex pour afficher le calcul de la moyenne
:param val_cara: caractère représentant les valeurs (x par défaut)
:param eff_cara: caractère représentant les effectifs (n par défaut)
:param end_cara: caractère représentant le nombre de valeurs (p par défaut)
:param moy_cara: nom de la moyenne (\\bar{x} par défaut)
:param var_var: nom de la variance (V par défaut)
:param ecar_var: nom de la variance (V par défaut)
:return: le code latex pour afficher le calcul de la moyenne
"""
ecart = self.ecart_type()
# On récupère le calcul de la variance
latex = self.variance_latex(val_cara, eff_cara, end_cara, moy_cara, var_cara)
latex += "\n\n"
# On y ajoute celui de l'écart-type (ya un soucis ici à cause du conflit entre format et {
latex += "{ecar_cara} &=& \\sqrt{{{var_cara}}} \\\\ \n".format(ecar_cara = ecar_cara, var_cara = var_cara)
latex += "\t &=& {ecart:.2f}".format(ecart = ecart)
return latex
# --------------------------
# Rendu latex
def moyenne_latex(self, val_cara = "x", eff_cara = "n", end_cara = "p", moy_cara= "\\bar{x}"):
"""
Renvoie le code latex pour afficher le calcul de la moyenne
:param val_cara: caractère représentant les valeurs (x par défaut)
:param eff_cara: caractère représentant les effectifs (n par défaut)
:param end_cara: caractère représentant le nombre de valeurs (p par défaut)
:param moy_cara: nom de la moyenne (\\bar{x} par défaut)
:return: le code latex pour afficher le calcul de la moyenne
"""
moy = self.moyenne()
latex = moy_cara + " &=& "
latex += "\\frac{{{x}_1 \\times {n}_1 + {x}_2 \\times {n}_2 + ... + {x}_{p} \\times {n}_{p}}}{{{n}_1 + {n}_2 + ... + {n}_p}} \\\\ \n".format(x = val_cara, n=eff_cara, p = end_cara)
latex += "\t &=& \\frac{"
for (i,v) in enumerate(self.valeurs):
latex += "{x:.2f} \\times {p:.2f} + ".format(x = v, p = self.effectifs[i])
latex = latex[:-2] # on enlève le + et l'espace de fin de calcul
latex += "}}{{{eff_tot}}}\\\\ \n".format(eff_tot = self.effectif_total)
latex += "\t &=& {moy:.2f}".format(moy=moy)
return latex
def variance_latex(self, val_cara = "x", eff_cara = "n", end_cara = "p", moy_cara= "\\bar{x}", var_cara = "V"):
"""
Renvoie le code latex pour afficher le calcul de la moyenne
:param val_cara: caractère représentant les valeurs (x par défaut)
:param eff_cara: caractère représentant les effectifs (n par défaut)
:param end_cara: caractère représentant le nombre de valeurs (p par défaut)
:param moy_cara: nom de la moyenne (\\bar{x} par défaut)
:param var_var: nom de la variance (V par défaut)
:return: le code latex pour afficher le calcul de la moyenne
"""
moy = self.moyenne()
var = self.variance()
latex = var_cara + " &=& "
latex += "\\frac{{ {n}_1 ({x}_1 - {moy})^2 + {n}_2 ({x}_2 - {moy})^2 + ... + {n}_{p} ({x}_{p} - {moy})^2}}{{{n}_1 + {n}_2 + ... + {n}_p}}\\\\ \n".format(x = val_cara, n=eff_cara, p = end_cara, moy = moy_cara)
latex += "\t &=& \\frac{ "
for (i,v) in enumerate(self.valeurs):
latex += "{p:.2f} ({x:.2f} - {moy:.2f})**2 + ".format(p = self.effectifs[i], x = v, moy = moy)
latex = latex[:-2] # on enlève le + et l'espace de fin de calcul
latex += "}}{{{eff_tot}}}\\\\ \n".format(eff_tot = self.effectif_total)
latex += "\t &=& {var:.2f}".format(var = var)
return latex
def ecart_type_latex(self, val_cara = "x", eff_cara = "n", end_cara = "p", moy_cara= "\\bar{x}", var_cara = "V", ecar_cara = "\\sigma"):
"""
Renvoie le code latex pour afficher le calcul de la moyenne
:param val_cara: caractère représentant les valeurs (x par défaut)
:param eff_cara: caractère représentant les effectifs (n par défaut)
:param end_cara: caractère représentant le nombre de valeurs (p par défaut)
:param moy_cara: nom de la moyenne (\\bar{x} par défaut)
:param var_var: nom de la variance (V par défaut)
:param ecar_var: nom de la variance (V par défaut)
:return: le code latex pour afficher le calcul de la moyenne
"""
ecart = self.ecart_type()
# On récupère le calcul de la variance
latex = self.variance_latex(val_cara, eff_cara, end_cara, moy_cara, var_cara)
latex += "\n\n"
# On y ajoute celui de l'écart-type (ya un soucis ici à cause du conflit entre format et {
latex += "{ecar_cara} &=& \\sqrt{{{var_cara}}} \\\\ \n".format(ecar_cara = ecar_cara, var_cara = var_cara)
latex += "\t &=& {ecart:.2f}".format(ecart = ecart)
return latex
def quartiles_latex(self):
""" Renvoie le code latex pour afficher le calcul des quartiles
:return : le code latex pour afficher le calcul des quartiles
"""
latex = self.quartile_latex()
latex += self.quartile_latex(1)
latex += self.quartile_latex(3)
return latex
def quartile_latex(self, quartile = 2):
""" Renvoie le code latex pour afficher le calcul du quartile
:param quartile: numéro du quartile
:return : le code latex pour afficher le calcul du quartile
"""
if quartile == 2 : # médiane
quartile_tpl = """ Position de la médiane: $\\dfrac{{\\mbox{{effectif total}}}}{{2}} = \\dfrac{{{eff_tot}}}{{2}} = {posi_q}$. Donc la médiane se trouve à la position: {posi_q_ceil}.
On a ainsi $Me = {val_q}$
"""
else:
quartile_tpl = """ Position de $Q_{q}$: $\\dfrac{{{q} \\times \\mbox{{effectif total}}}}{{4}} = \\dfrac{{{q} \\times {eff_tot}}}{{4}} = {posi_q}$. Donc $Q_{q}$ se trouve à la position: {posi_q_ceil}.
On a ainsi $Q_{q} = {val_q}$
"""
posi_q_ceil , posi_q = self.posi_quartile(quartile)
val_q = self.quartile(quartile)
latex = quartile_tpl.format(eff_tot = self.effectif_total, q = quartile, posi_q = posi_q, posi_q_ceil = posi_q_ceil, val_q = val_q)
return latex
def tabular_latex(self, nbr_lines = 1):
""" Latex code to display dataset as a tabular """
d_per_line = self.effectif_total() // nbr_lines
d_last_line = self.effectif_total() % d_per_line
splited_data = [self[x:x+d_per_line] for x in range(0, self.effectif_total(), d_per_line)]
# On ajoute les éléments manquant pour la dernière line
if d_last_line:
splited_data[-1] += [' ']*(d_per_line - d_last_line)
# Construction du tableau
latex = "\\begin{{tabular}}{{|c|*{{{nbr_col}}}{{c|}}}} \n".format(nbr_col = d_per_line)
latex += "\t\t \hline \n"
d_lines = [' & '.join(map(str,l)) for l in splited_data]
latex += " \\\\ \n \\hline \n".join(d_lines)
latex += " \\\\ \n \\hline \n"
latex += "\\end{tabular}"
return latex
if __name__ == '__main__':
valeurs = [65, 75, 85, 95, 105, 115, 125, 135]
valeurs.sort()
print(valeurs)
effectifs = [ 15, 2, 21, 24, 12, 9, 5, 2]
s = Dataset()
s.set_values(valeurs, effectifs)
print(s.effectif_total)
print(s.valeurs)
print(s.effectifs)
print(s.data)
# print(s.tabular_latex())
# print("Moyenne ", s.moyenne())
# print(s.variance())
# print(s.ecart_type())
print("\n-----------------------\n")
print(s.moyenne_latex())
print("\n-----------------------\n")
print(s.variance_latex())
print("\n-----------------------\n")
print(s.ecart_type_latex())
# print(s.quartiles())
print("\n-----------------------\n")
print(s.quartile_latex())
print(s.quartile_latex(1))
print(s.quartile_latex(3))
# -----------------------------
# Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
# cursor: 16 del