Réécrit le tableau de synthèse du jury PE par tag avec des DataFrame + limite l'affichage aux aggrégats significatifs (avec notes)
This commit is contained in:
parent
0bf0311f2f
commit
c9af2345fb
@ -321,51 +321,131 @@ class JuryPE(object):
|
||||
"""
|
||||
|
||||
etudids = list(self.diplomes_ids)
|
||||
aggregats = pe_comp.TOUS_LES_PARCOURS
|
||||
|
||||
donnees = {}
|
||||
|
||||
# Les données des étudiants
|
||||
donnees_etudiants = {}
|
||||
for etudid in etudids:
|
||||
etudiant = self.etudiants.identites[etudid]
|
||||
donnees[etudid] = {
|
||||
donnees_etudiants[etudid] = {
|
||||
("Identité", "", "Civilite"): etudiant.civilite_str,
|
||||
("Identité", "", "Nom"): etudiant.nom,
|
||||
("Identité", "", "Prenom"): etudiant.prenom,
|
||||
}
|
||||
df_synthese = pd.DataFrame.from_dict(donnees_etudiants, orient="index")
|
||||
|
||||
for aggregat in aggregats:
|
||||
# Le dictionnaire par défaut des moyennes
|
||||
donnees[etudid] |= get_defaut_dict_synthese_aggregat(
|
||||
aggregat, self.diplome
|
||||
)
|
||||
# Ajout des aggrégats
|
||||
aggregats = pe_comp.TOUS_LES_PARCOURS
|
||||
|
||||
# La trajectoire de l'étudiant sur l'aggrégat
|
||||
for aggregat in aggregats:
|
||||
descr = pe_comp.PARCOURS[aggregat]["descr"]
|
||||
|
||||
# Les trajectoires (tagguées) suivies par les étudiants pour l'aggrégat et le tag
|
||||
# considéré
|
||||
trajectoires_tagguees = []
|
||||
for etudid in etudids:
|
||||
trajectoire = self.trajectoires.suivi[etudid][aggregat]
|
||||
if trajectoire:
|
||||
trajectoire_tagguee = self.trajectoires_tagguees[
|
||||
trajectoire.trajectoire_id
|
||||
]
|
||||
if tag in trajectoire_tagguee.moyennes_tags:
|
||||
# La trajectoire tagguée
|
||||
moy_trajectoire_tag = trajectoire_tagguee.moyennes_tags[tag]
|
||||
if moy_trajectoire_tag.is_significatif():
|
||||
# L'interclassement
|
||||
interclass = self.interclassements_taggues[aggregat]
|
||||
tid = trajectoire.trajectoire_id
|
||||
trajectoire_tagguee = self.trajectoires_tagguees[tid]
|
||||
if (
|
||||
tag in trajectoire_tagguee.moyennes_tags
|
||||
and trajectoire_tagguee not in trajectoires_tagguees
|
||||
):
|
||||
trajectoires_tagguees.append(trajectoire_tagguee)
|
||||
|
||||
# Injection des données dans un dictionnaire
|
||||
donnees[etudid] |= get_dict_synthese_aggregat(
|
||||
aggregat, trajectoire_tagguee, interclass, etudid, tag, self.diplome
|
||||
)
|
||||
# Ajout des notes
|
||||
notes = pd.DataFrame(index=etudids, columns=[ [descr], [""], ["note"] ])
|
||||
|
||||
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)
|
||||
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]
|
||||
|
||||
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"] ],
|
||||
)
|
||||
|
||||
# Les classements
|
||||
rangs = moy_traj.get_df_rangs_pertinents()
|
||||
|
||||
etudids_communs = rangs.index.intersection(etudids)
|
||||
|
||||
donnees.loc[
|
||||
etudids_communs, (descr, nom_stat_promo, "class.")
|
||||
] = rangs.loc[etudids_communs, "rangs"]
|
||||
|
||||
# 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()
|
||||
|
||||
df_synthese = df_synthese.join(donnees)
|
||||
# Fin de l'aggrégat
|
||||
# Construction du dataFrame
|
||||
df = pd.DataFrame.from_dict(donnees, orient="index")
|
||||
|
||||
# Tri par nom/prénom
|
||||
df.sort_values(
|
||||
df_synthese.sort_values(
|
||||
by=[("Identité", "", "Nom"), ("Identité", "", "Prenom")], inplace=True
|
||||
)
|
||||
return df
|
||||
return df_synthese
|
||||
|
||||
def synthetise_jury_par_etudiants(self) -> dict[pd.DataFrame]:
|
||||
"""Synthétise tous les résultats du jury PE dans des dataframes,
|
||||
@ -420,10 +500,14 @@ class JuryPE(object):
|
||||
# L'interclassement
|
||||
interclass = self.interclassements_taggues[aggregat]
|
||||
|
||||
|
||||
# Injection des données dans un dictionnaire
|
||||
donnees[tag] |= get_dict_synthese_aggregat(
|
||||
aggregat, trajectoire_tagguee, interclass, etudid, tag, self.diplome
|
||||
aggregat,
|
||||
trajectoire_tagguee,
|
||||
interclass,
|
||||
etudid,
|
||||
tag,
|
||||
self.diplome,
|
||||
)
|
||||
|
||||
# Fin de l'aggrégat
|
||||
@ -597,12 +681,12 @@ def get_dict_synthese_aggregat(
|
||||
if not pd.isna(note) and note != np.nan:
|
||||
# Les moyennes de cette trajectoire
|
||||
donnees |= {
|
||||
(descr, "", "note"): note,
|
||||
(descr, NOM_STAT_GROUPE, "class."): classement,
|
||||
(descr, NOM_STAT_GROUPE, "min"): nmin,
|
||||
(descr, NOM_STAT_GROUPE, "moy"): nmoy,
|
||||
(descr, NOM_STAT_GROUPE, "max"): nmax,
|
||||
}
|
||||
(descr, "", "note"): note,
|
||||
(descr, NOM_STAT_GROUPE, "class."): classement,
|
||||
(descr, NOM_STAT_GROUPE, "min"): nmin,
|
||||
(descr, NOM_STAT_GROUPE, "moy"): nmoy,
|
||||
(descr, NOM_STAT_GROUPE, "max"): nmax,
|
||||
}
|
||||
|
||||
# L'interclassement
|
||||
moy_tag = interclassement_taggue.moyennes_tags[tag]
|
||||
|
@ -43,14 +43,15 @@ import numpy as np
|
||||
from app import ScoValueError
|
||||
from app.comp.moy_sem import comp_ranks_series
|
||||
from app.pe import pe_affichage
|
||||
from app.pe.pe_affichage import SANS_NOTE
|
||||
from app.scodoc import sco_utils as scu
|
||||
import pandas as pd
|
||||
|
||||
|
||||
TAGS_RESERVES = ["but"]
|
||||
|
||||
class MoyenneTag():
|
||||
|
||||
class MoyenneTag:
|
||||
def __init__(self, tag: str, notes: pd.Series):
|
||||
"""Classe centralisant la synthèse des moyennes/classements d'une série
|
||||
d'étudiants à un tag donné, en stockant un dictionnaire :
|
||||
@ -104,7 +105,7 @@ class MoyenneTag():
|
||||
(_, class_gen_ue_non_nul) = comp_ranks_series(notes_non_nulles)
|
||||
|
||||
# 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 = pd.Series(np.nan, index=notes.index) # , dtype="Int64")
|
||||
class_gen_ue[indices] = class_gen_ue_non_nul[indices]
|
||||
|
||||
synthese = {
|
||||
@ -117,6 +118,27 @@ class MoyenneTag():
|
||||
}
|
||||
return synthese
|
||||
|
||||
def get_df_notes(self, arrondi=False):
|
||||
"""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
|
||||
|
||||
def get_df_rangs_pertinents(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)
|
||||
|
||||
nb_inscrit = self.synthese["nb_inscrits"]
|
||||
|
||||
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)
|
||||
@ -136,8 +158,8 @@ 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.synthese["classements"].loc[etudid]
|
||||
nb_inscrit = self.synthese["nb_inscrits"]
|
||||
if not pd.isna(classement):
|
||||
classement = int(classement)
|
||||
return f"{classement}/{nb_inscrit}"
|
||||
@ -148,6 +170,7 @@ class MoyenneTag():
|
||||
"""Indique si la moyenne est significative (c'est-à-dire à des notes)"""
|
||||
return self.synthese["nb_inscrits"] > 0
|
||||
|
||||
|
||||
class TableTag(object):
|
||||
def __init__(self):
|
||||
"""Classe centralisant différentes méthodes communes aux
|
||||
@ -203,7 +226,3 @@ class TableTag(object):
|
||||
dict_series[tag] = moy_tag.synthese["notes"]
|
||||
df = pd.DataFrame(dict_series)
|
||||
return df
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -64,12 +64,15 @@ class TrajectoireTag(TableTag):
|
||||
"""
|
||||
TableTag.__init__(self)
|
||||
|
||||
# La trajectoire associée
|
||||
self.trajectoire_id = trajectoire.trajectoire_id
|
||||
self.trajectoire = trajectoire
|
||||
|
||||
# Le nom de la trajectoire tagguée (identique à la trajectoire)
|
||||
self.trajectoire_id = trajectoire.trajectoire_id
|
||||
"""Identifiant de la trajectoire tagguée"""
|
||||
|
||||
self.trajectoire = trajectoire
|
||||
"""Trajectoire associée à la trajectoire tagguée"""
|
||||
|
||||
self.nom = self.get_repr()
|
||||
"""Représentation textuelle de la trajectoire tagguée"""
|
||||
|
||||
self.formsemestre_terminal = trajectoire.formsemestre_final
|
||||
"""Le formsemestre terminal"""
|
||||
@ -110,6 +113,10 @@ class TrajectoireTag(TableTag):
|
||||
moy_gen_tag = self.notes[tag]
|
||||
self.moyennes_tags[tag] = MoyenneTag(tag, moy_gen_tag)
|
||||
|
||||
def __eq__(self, other):
|
||||
"""Egalité de 2 trajectoires tagguées sur la base de leur identifiant"""
|
||||
return self.trajectoire_id == other.trajectoire_id
|
||||
|
||||
def get_repr(self, verbose=False) -> str:
|
||||
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
||||
est basée)"""
|
||||
|
Loading…
Reference in New Issue
Block a user