From f7b31425e2c5c3d23a255d72544ae4c080e82fe4 Mon Sep 17 00:00:00 2001 From: Benjamin Bertrand Date: Sat, 9 Jan 2016 18:14:18 +0300 Subject: [PATCH] random generation for Dataset --- pymath/stat/dataset.py | 294 ++++++++++------------------------------- 1 file changed, 69 insertions(+), 225 deletions(-) diff --git a/pymath/stat/dataset.py b/pymath/stat/dataset.py index 1c104b6..ddb2f31 100644 --- a/pymath/stat/dataset.py +++ b/pymath/stat/dataset.py @@ -8,6 +8,7 @@ # from math import sqrt, ceil +from random import randint, uniform, gauss class Dataset(list): """ A dataset (a list) with statistics and latex rendering methods @@ -24,6 +25,71 @@ class Dataset(list): >>> s.sd() 28.86607004772212 """ + + @classmethod + def random(cls, length, data_name = "Valeurs", \ + distrib = gauss, rd_args = (0,1), \ + nbr_format = lambda x:round(x,2), \ + v_min = None, v_max = None, \ + exact_mean = None): + """ Create a random Dataset. + + :param length: length of the dataset + :param distrib: Distribution of the data set. It can be a function or string from ["randint", "uniform", "gauss"] + :param rd_args: arguments to pass to distrib + :param nbr_format: function which format value + :param v_min: minimum accepted value + :param v_max: maximum accepted value + :param exact_mean: if set, the last generated number will be create in order that the computed mean is exacly equal to "exact_mean" + + : Exemple: + >>> Dataset.random(10) + >>> Dataset.random(10, distrib = uniform, rd_args = (5, 10)) + >>> Dataset.random(10, distrib = "uniform", rd_args = (5, 10)) + >>> Dataset.random(10, v_min = 0) + >>> Dataset.random(10, exact_mean = 0) + >>> Dataset.random(10, distrib = gauss, rd_args = (50,20), nbr_format = int) + + """ + # if exact_mean is set, we create automaticaly only length-1 value + if exact_mean != None: + length = length - 1 + + # build function to test created values + if v_min == None: + v1 = lambda x: True + else: + v1 = lambda x: x >= v_min + if v_max == None: + v2 = lambda x: True + else: + v2 = lambda x: x <= v_max + validate = lambda x : v1(x) and v2(x) + + # get distrib function + distribs = {"gauss": gauss, "uniform": uniform, "randint":randint} + try: + distrib(*rd_args) + except TypeError: + distrib = distribs[distrib] + + # building values + data = [] + for _ in range(length): + valid = False + while not valid: + v = nbr_format(distrib(*rd_args)) + valid = validate(v) + data.append(v) + + # Build last value + if exact_mean != None: + last_v = nbr_format((length+1) * exact_mean - sum(data)) + if not validate(last_v): + raise ValueError("Can't build the last value. Conflict between v_min/v_max and exact_mean") + data.append(last_v) + + return cls(data, data_name = data_name) def __init__(self, data = [], data_name = "Valeurs"): """ @@ -46,6 +112,9 @@ class Dataset(list): except TypeError: self += [data] + # -------------------------- + # Stat tools + def effectif_total(self): return len(self) @@ -122,199 +191,9 @@ class Dataset(list): """ 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 @@ -336,41 +215,6 @@ On a ainsi $Q_{q} = {val_q}$ 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)) - # -----------------------------