diff --git a/app/pe/pe_jury.py b/app/pe/pe_jury.py index 30f6da83..79aa21ef 100644 --- a/app/pe/pe_jury.py +++ b/app/pe/pe_jury.py @@ -353,90 +353,90 @@ class JuryPE(object): ): trajectoires_tagguees.append(trajectoire_tagguee) - # Ajout des notes - notes = pd.DataFrame(index=etudids, columns=[ [descr], [""], ["note"] ]) - + # Combien de notes vont être injectées ? nbre_notes_injectees = 0 for traj in trajectoires_tagguees: moy_traj = traj.moyennes_tags[tag] - notes_traj = moy_traj.get_df_notes(arrondi=True) - etudids_communs = notes_traj.index.intersection(etudids) + inscrits_traj = moy_traj.inscrits_ids + etudids_communs = set(etudids) & set(inscrits_traj) nbre_notes_injectees += len(etudids_communs) - notes.loc[etudids_communs, (descr, "", "note")] = notes_traj.loc[etudids_communs, "notes"] # Si l'aggrégat est significatif (aka il y a des notes) if nbre_notes_injectees > 0: - df_synthese = df_synthese.join(notes) - - # Ajout des classements & statistiques - donnees = pd.DataFrame( - index=etudids, - columns=[ [descr]*4, [NOM_STAT_GROUPE]*4, ["class.", "min", "moy", "max"] ], - ) - # donnees[(descr, NOM_STAT_GROUPE, "class.")] = donnees[ - # (descr, NOM_STAT_GROUPE, "class.") - # ].astype(str) - # donnees[(descr, NOM_STAT_GROUPE, "class.")] = np.nan - - for traj in trajectoires_tagguees: - moy_traj = traj.moyennes_tags[tag] - - # Les classements - rangs = moy_traj.get_df_rangs_pertinents() - - # Les etudids communs pour la trajectoire - etudids_communs = rangs.index.intersection(etudids) - - donnees.loc[ - etudids_communs, (descr, NOM_STAT_GROUPE, "class.") - ] = rangs.loc[etudids_communs, "rangs"] - - # Le min - donnees.loc[ - etudids_communs, (descr, NOM_STAT_GROUPE, "min") - ] = moy_traj.get_min_for_df() - # Le max - donnees.loc[ - etudids_communs, (descr, NOM_STAT_GROUPE, "max") - ] = moy_traj.get_max_for_df() - # La moyenne - donnees.loc[ - etudids_communs, (descr, NOM_STAT_GROUPE, "moy") - ] = moy_traj.get_moy_for_df() - - df_synthese = df_synthese.join(donnees) - - # Ajoute les données d'interclassement - interclass = self.interclassements_taggues[aggregat] - moy_traj = interclass.moyennes_tags[tag] - + # Ajout des données classements & statistiques nom_stat_promo = f"{NOM_STAT_PROMO} {self.diplome}" donnees = pd.DataFrame( index=etudids, - columns=[ [descr]*4, [nom_stat_promo]*4, ["class.", "min", "moy", "max"] ], + columns=[ + [descr] * (1 + 4 * 2), + [""] + [NOM_STAT_GROUPE] * 4 + [nom_stat_promo] * 4, + ["note"] + ["class.", "min", "moy", "max"] * 2, + ], ) - # Les classements - rangs = moy_traj.get_df_rangs_pertinents() + for traj in trajectoires_tagguees: + # Les données des trajectoires_tagguees + moy_traj = traj.moyennes_tags[tag] - etudids_communs = rangs.index.intersection(etudids) + # Les étudiants communs entre tableur de synthèse et trajectoires + inscrits_traj = moy_traj.inscrits_ids + etudids_communs = list(set(etudids) & set(inscrits_traj)) - donnees.loc[ - etudids_communs, (descr, nom_stat_promo, "class.") - ] = rangs.loc[etudids_communs, "rangs"] + # Les notes + champ = (descr, "", "note") + notes_traj = moy_traj.get_notes() + donnees.loc[etudids_communs, champ] = notes_traj.loc[ + etudids_communs] - # Le min - donnees.loc[ - etudids_communs, (descr, nom_stat_promo, "min") - ] = moy_traj.get_min_for_df() - # Le max - donnees.loc[ - etudids_communs, (descr, nom_stat_promo, "max") - ] = moy_traj.get_max_for_df() - # La moyenne - donnees.loc[ - etudids_communs, (descr, nom_stat_promo, "moy") - ] = moy_traj.get_moy_for_df() + # Les rangs + champ = (descr, NOM_STAT_GROUPE, "class.") + rangs = moy_traj.get_rangs_inscrits() + donnees.loc[etudids_communs, champ] = rangs.loc[ + etudids_communs + ] + + # Les mins + champ = (descr, NOM_STAT_GROUPE, "min") + mins = moy_traj.get_min() + donnees.loc[etudids_communs, champ] = mins.loc[etudids_communs] + + # Les max + champ = (descr, NOM_STAT_GROUPE, "max") + maxs = moy_traj.get_max() + donnees.loc[etudids_communs, champ] = maxs.loc[etudids_communs] + + # Les moys + champ = (descr, NOM_STAT_GROUPE, "moy") + moys = moy_traj.get_max() + donnees.loc[etudids_communs, champ] = moys.loc[etudids_communs] + + # Ajoute les données d'interclassement + interclass = self.interclassements_taggues[aggregat] + moy_interclass = interclass.moyennes_tags[tag] + + # Les étudiants communs entre tableur de synthèse et l'interclassement + inscrits_interclass = moy_interclass.inscrits_ids + etudids_communs = list(set(etudids) & set(inscrits_interclass)) + + # Les classements d'interclassement + champ = (descr, nom_stat_promo, "class.") + rangs = moy_interclass.get_rangs_inscrits() + donnees.loc[etudids_communs, champ] = rangs.loc[etudids_communs] + + # Les mins + champ = (descr, nom_stat_promo, "min") + mins = moy_interclass.get_min() + donnees.loc[etudids_communs, champ] = mins.loc[etudids_communs] + + # Les max + champ = (descr, nom_stat_promo, "max") + maxs = moy_interclass.get_max() + donnees.loc[etudids_communs, champ] = maxs.loc[etudids_communs] + + # Les moys + champ = (descr, nom_stat_promo, "moy") + moys = moy_interclass.get_max() + donnees.loc[etudids_communs, champ] = moys.loc[etudids_communs] df_synthese = df_synthese.join(donnees) # Fin de l'aggrégat diff --git a/app/pe/pe_tabletags.py b/app/pe/pe_tabletags.py index b85bb554..68be8772 100644 --- a/app/pe/pe_tabletags.py +++ b/app/pe/pe_tabletags.py @@ -73,8 +73,14 @@ class MoyenneTag: """ self.tag = tag """Le tag associé à la moyenne""" - self.synthese = self.comp_moy_et_stat(notes) - """La synthèse des notes/classements/statistiques""" + self.etudids = list(notes.index) # calcul à venir + """Les id des étudiants""" + self.inscrits_ids = notes[notes.notnull()].index.to_list() + """Les id des étudiants dont la moyenne est non nulle""" + self.df: pd.DataFrame = self.comp_moy_et_stat(notes) + """Le dataframe retraçant les moyennes/classements/statistiques""" + self.synthese = self.to_dict() + """La synthèse (dictionnaire) des notes/classements/statistiques""" def __eq__(self, other): """Egalité de deux MoyenneTag lorsque leur tag sont identiques""" @@ -94,54 +100,85 @@ class MoyenneTag: Un dictionnaire stockant les notes, les classements, le min, le max, la moyenne, le nb de notes (donc d'inscrits) """ - # Supprime d'éventuels chaines de caractères dans les notes + df = pd.DataFrame( + np.nan, + index=self.etudids, + columns=[ + "note", + "classement", + "rang", + "min", + "max", + "moy", + "nb_etuds", + "nb_inscrits", + ], + ) + + # Supprime d'éventuelles chaines de caractères dans les notes notes = pd.to_numeric(notes, errors="coerce") + df["note"] = notes - # Les indices des ... et les notes non nulles/pertinentes - indices = notes.notnull() - notes_non_nulles = notes[indices] + # Les nb d'étudiants & nb d'inscrits + df["nb_etuds"] = len(self.etudids) + df.loc[self.inscrits_ids, "nb_inscrits"] = len(self.inscrits_ids) - # Les classements sur les notes non nulles - (_, class_gen_ue_non_nul) = comp_ranks_series(notes_non_nulles) + # Le classement des inscrits + notes_non_nulles = notes[self.inscrits_ids] + (class_str, class_int) = comp_ranks_series(notes_non_nulles) + df.loc[self.inscrits_ids, "classement"] = class_int - # Les classements (toutes notes confondues, avec NaN si pas de notes) - class_gen_ue = pd.Series(np.nan, index=notes.index) # , dtype="Int64") - class_gen_ue[indices] = class_gen_ue_non_nul[indices] + # Le rang (classement/nb_inscrit) + df["rang"] = df["rang"].astype(str) + df.loc[self.inscrits_ids, "rang"] = ( + df.loc[self.inscrits_ids, "classement"].astype(int).astype(str) + + "/" + + df.loc[self.inscrits_ids, "nb_inscrits"].astype(int).astype(str) + ) + # Les stat (des inscrits) + df.loc[self.inscrits_ids, "min"] = notes.min() + df.loc[self.inscrits_ids, "max"] = notes.max() + df.loc[self.inscrits_ids, "moy"] = notes.mean() + + return df + + def to_dict(self) -> dict: + """Renvoie un dictionnaire de synthèse des moyennes/classements/statistiques""" synthese = { - "notes": notes, - "classements": class_gen_ue, - "min": notes.min(), - "max": notes.max(), - "moy": notes.mean(), - "nb_inscrits": sum(indices), + "notes": self.df["note"], + "classements": self.df["classement"], + "min": self.df["min"].mean(), + "max": self.df["max"].mean(), + "moy": self.df["moy"].mean(), + "nb_inscrits": self.df["nb_inscrits"].mean(), } return synthese - def get_df_notes(self, arrondi=False): + def get_notes(self): """Série des notes, arrondies à 2 chiffres après la virgule""" - if arrondi: - serie = self.synthese["notes"].round(2) - else: - serie = self.synthese["notes"] - df = serie.to_frame("notes") - return df + return self.df["note"].round(2) - def get_df_rangs_pertinents(self) -> pd.Series: + def get_rangs_inscrits(self) -> pd.Series: """Série des rangs classement/nbre_inscrit""" - classement = self.synthese["classements"] - indices = classement[classement.notnull()].index.to_list() - classement_non_nul = classement.loc[indices].to_frame("classements") - classement_non_nul.insert(1, "rangs", np.nan) + return self.df["rang"] - nb_inscrit = self.synthese["nb_inscrits"] + def get_min(self) -> pd.Series: + """Série des min""" + return self.df["min"].round(2) + + def get_max(self) -> pd.Series: + """Série des max""" + return self.df["max"].round(2) + + def get_moy(self) -> pd.Series: + """Série des moy""" + return self.df["moy"].round(2) - classement_non_nul["rangs"] = classement_non_nul["classements"].astype(int).astype(str) + "/" + str(nb_inscrit) - return classement_non_nul["rangs"].to_frame("rangs") def get_note_for_df(self, etudid: int): """Note d'un étudiant donné par son etudid""" - return round(self.synthese["notes"].loc[etudid], 2) + return round(self.df["note"].loc[etudid], 2) def get_min_for_df(self) -> float: """Min renseigné pour affichage dans un df""" @@ -158,11 +195,9 @@ class MoyenneTag: def get_class_for_df(self, etudid: int) -> str: """Classement ramené au nombre d'inscrits, pour un étudiant donné par son etudid""" - classement = self.synthese["classements"].loc[etudid] - nb_inscrit = self.synthese["nb_inscrits"] + classement = self.df["rang"].loc[etudid] if not pd.isna(classement): - classement = int(classement) - return f"{classement}/{nb_inscrit}" + return classement else: return pe_affichage.SANS_NOTE