forked from ScoDoc/ScoDoc
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)
|
etudids = list(self.diplomes_ids)
|
||||||
aggregats = pe_comp.TOUS_LES_PARCOURS
|
|
||||||
|
|
||||||
donnees = {}
|
|
||||||
|
|
||||||
|
# Les données des étudiants
|
||||||
|
donnees_etudiants = {}
|
||||||
for etudid in etudids:
|
for etudid in etudids:
|
||||||
etudiant = self.etudiants.identites[etudid]
|
etudiant = self.etudiants.identites[etudid]
|
||||||
donnees[etudid] = {
|
donnees_etudiants[etudid] = {
|
||||||
("Identité", "", "Civilite"): etudiant.civilite_str,
|
("Identité", "", "Civilite"): etudiant.civilite_str,
|
||||||
("Identité", "", "Nom"): etudiant.nom,
|
("Identité", "", "Nom"): etudiant.nom,
|
||||||
("Identité", "", "Prenom"): etudiant.prenom,
|
("Identité", "", "Prenom"): etudiant.prenom,
|
||||||
}
|
}
|
||||||
|
df_synthese = pd.DataFrame.from_dict(donnees_etudiants, orient="index")
|
||||||
|
|
||||||
|
# Ajout des aggrégats
|
||||||
|
aggregats = pe_comp.TOUS_LES_PARCOURS
|
||||||
|
|
||||||
for aggregat in aggregats:
|
for aggregat in aggregats:
|
||||||
# Le dictionnaire par défaut des moyennes
|
descr = pe_comp.PARCOURS[aggregat]["descr"]
|
||||||
donnees[etudid] |= get_defaut_dict_synthese_aggregat(
|
|
||||||
aggregat, self.diplome
|
|
||||||
)
|
|
||||||
|
|
||||||
# La trajectoire de l'étudiant sur l'aggrégat
|
# 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]
|
trajectoire = self.trajectoires.suivi[etudid][aggregat]
|
||||||
if trajectoire:
|
if trajectoire:
|
||||||
trajectoire_tagguee = self.trajectoires_tagguees[
|
tid = trajectoire.trajectoire_id
|
||||||
trajectoire.trajectoire_id
|
trajectoire_tagguee = self.trajectoires_tagguees[tid]
|
||||||
]
|
if (
|
||||||
if tag in trajectoire_tagguee.moyennes_tags:
|
tag in trajectoire_tagguee.moyennes_tags
|
||||||
# La trajectoire tagguée
|
and trajectoire_tagguee not in trajectoires_tagguees
|
||||||
moy_trajectoire_tag = trajectoire_tagguee.moyennes_tags[tag]
|
):
|
||||||
if moy_trajectoire_tag.is_significatif():
|
trajectoires_tagguees.append(trajectoire_tagguee)
|
||||||
# L'interclassement
|
|
||||||
interclass = self.interclassements_taggues[aggregat]
|
|
||||||
|
|
||||||
# Injection des données dans un dictionnaire
|
# Ajout des notes
|
||||||
donnees[etudid] |= get_dict_synthese_aggregat(
|
notes = pd.DataFrame(index=etudids, columns=[ [descr], [""], ["note"] ])
|
||||||
aggregat, trajectoire_tagguee, interclass, etudid, tag, self.diplome
|
|
||||||
|
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
|
# Fin de l'aggrégat
|
||||||
# Construction du dataFrame
|
|
||||||
df = pd.DataFrame.from_dict(donnees, orient="index")
|
|
||||||
|
|
||||||
# Tri par nom/prénom
|
# Tri par nom/prénom
|
||||||
df.sort_values(
|
df_synthese.sort_values(
|
||||||
by=[("Identité", "", "Nom"), ("Identité", "", "Prenom")], inplace=True
|
by=[("Identité", "", "Nom"), ("Identité", "", "Prenom")], inplace=True
|
||||||
)
|
)
|
||||||
return df
|
return df_synthese
|
||||||
|
|
||||||
def synthetise_jury_par_etudiants(self) -> dict[pd.DataFrame]:
|
def synthetise_jury_par_etudiants(self) -> dict[pd.DataFrame]:
|
||||||
"""Synthétise tous les résultats du jury PE dans des dataframes,
|
"""Synthétise tous les résultats du jury PE dans des dataframes,
|
||||||
@ -420,10 +500,14 @@ class JuryPE(object):
|
|||||||
# L'interclassement
|
# L'interclassement
|
||||||
interclass = self.interclassements_taggues[aggregat]
|
interclass = self.interclassements_taggues[aggregat]
|
||||||
|
|
||||||
|
|
||||||
# Injection des données dans un dictionnaire
|
# Injection des données dans un dictionnaire
|
||||||
donnees[tag] |= get_dict_synthese_aggregat(
|
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
|
# Fin de l'aggrégat
|
||||||
|
@ -43,14 +43,15 @@ import numpy as np
|
|||||||
from app import ScoValueError
|
from app import ScoValueError
|
||||||
from app.comp.moy_sem import comp_ranks_series
|
from app.comp.moy_sem import comp_ranks_series
|
||||||
from app.pe import pe_affichage
|
from app.pe import pe_affichage
|
||||||
|
from app.pe.pe_affichage import SANS_NOTE
|
||||||
from app.scodoc import sco_utils as scu
|
from app.scodoc import sco_utils as scu
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
|
|
||||||
TAGS_RESERVES = ["but"]
|
TAGS_RESERVES = ["but"]
|
||||||
|
|
||||||
class MoyenneTag():
|
|
||||||
|
|
||||||
|
class MoyenneTag:
|
||||||
def __init__(self, tag: str, notes: pd.Series):
|
def __init__(self, tag: str, notes: pd.Series):
|
||||||
"""Classe centralisant la synthèse des moyennes/classements d'une série
|
"""Classe centralisant la synthèse des moyennes/classements d'une série
|
||||||
d'étudiants à un tag donné, en stockant un dictionnaire :
|
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)
|
(_, class_gen_ue_non_nul) = comp_ranks_series(notes_non_nulles)
|
||||||
|
|
||||||
# Les classements (toutes notes confondues, avec NaN si pas de notes)
|
# 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]
|
class_gen_ue[indices] = class_gen_ue_non_nul[indices]
|
||||||
|
|
||||||
synthese = {
|
synthese = {
|
||||||
@ -117,6 +118,27 @@ class MoyenneTag():
|
|||||||
}
|
}
|
||||||
return synthese
|
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):
|
def get_note_for_df(self, etudid: int):
|
||||||
"""Note d'un étudiant donné par son etudid"""
|
"""Note d'un étudiant donné par son etudid"""
|
||||||
return round(self.synthese["notes"].loc[etudid], 2)
|
return round(self.synthese["notes"].loc[etudid], 2)
|
||||||
@ -136,8 +158,8 @@ class MoyenneTag():
|
|||||||
def get_class_for_df(self, etudid: int) -> str:
|
def get_class_for_df(self, etudid: int) -> str:
|
||||||
"""Classement ramené au nombre d'inscrits,
|
"""Classement ramené au nombre d'inscrits,
|
||||||
pour un étudiant donné par son etudid"""
|
pour un étudiant donné par son etudid"""
|
||||||
classement = self.synthese['classements'].loc[etudid]
|
classement = self.synthese["classements"].loc[etudid]
|
||||||
nb_inscrit = self.synthese['nb_inscrits']
|
nb_inscrit = self.synthese["nb_inscrits"]
|
||||||
if not pd.isna(classement):
|
if not pd.isna(classement):
|
||||||
classement = int(classement)
|
classement = int(classement)
|
||||||
return f"{classement}/{nb_inscrit}"
|
return f"{classement}/{nb_inscrit}"
|
||||||
@ -148,6 +170,7 @@ class MoyenneTag():
|
|||||||
"""Indique si la moyenne est significative (c'est-à-dire à des notes)"""
|
"""Indique si la moyenne est significative (c'est-à-dire à des notes)"""
|
||||||
return self.synthese["nb_inscrits"] > 0
|
return self.synthese["nb_inscrits"] > 0
|
||||||
|
|
||||||
|
|
||||||
class TableTag(object):
|
class TableTag(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Classe centralisant différentes méthodes communes aux
|
"""Classe centralisant différentes méthodes communes aux
|
||||||
@ -203,7 +226,3 @@ class TableTag(object):
|
|||||||
dict_series[tag] = moy_tag.synthese["notes"]
|
dict_series[tag] = moy_tag.synthese["notes"]
|
||||||
df = pd.DataFrame(dict_series)
|
df = pd.DataFrame(dict_series)
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,12 +64,15 @@ class TrajectoireTag(TableTag):
|
|||||||
"""
|
"""
|
||||||
TableTag.__init__(self)
|
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()
|
self.nom = self.get_repr()
|
||||||
|
"""Représentation textuelle de la trajectoire tagguée"""
|
||||||
|
|
||||||
self.formsemestre_terminal = trajectoire.formsemestre_final
|
self.formsemestre_terminal = trajectoire.formsemestre_final
|
||||||
"""Le formsemestre terminal"""
|
"""Le formsemestre terminal"""
|
||||||
@ -110,6 +113,10 @@ class TrajectoireTag(TableTag):
|
|||||||
moy_gen_tag = self.notes[tag]
|
moy_gen_tag = self.notes[tag]
|
||||||
self.moyennes_tags[tag] = MoyenneTag(tag, moy_gen_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:
|
def get_repr(self, verbose=False) -> str:
|
||||||
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
||||||
est basée)"""
|
est basée)"""
|
||||||
|
Loading…
Reference in New Issue
Block a user