import numpy as np import pandas as pd from app import comp from app.comp.moy_sem import comp_ranks_series from app.pe.moys import pe_moy from app.scodoc.sco_utils import ModuleType CODE_MOY_UE = "UEs" CODE_MOY_COMPETENCES = "Compétences" CHAMP_GENERAL = "Général" # Nom du champ de la moyenne générale class MoyennesTag: def __init__( self, tag: str, type_moyenne: str, matrice_notes_gen: pd.DataFrame, # etudids x colonnes matrice_coeffs: pd.DataFrame, # etudids x colonnes ): """Classe centralisant la synthèse des moyennes/classements d'une série d'étudiants à un tag donné, en différenciant les notes obtenues aux UE et au général (toutes UEs confondues) Args: tag: Un tag matrice_notes_gen: Les moyennes (etudid x acronymes_ues ou etudid x compétences) aux différentes UEs ou compétences # notes_gen: Une série de notes (moyenne) sous forme d'un ``pd.Series`` (toutes UEs confondues) """ self.tag = tag """Le tag associé aux moyennes""" self.type = type_moyenne """Le type de moyennes (par UEs ou par compétences)""" # Les moyennes par UE/compétences (ressources/SAEs confondues) self.matrice_notes_gen: pd.DataFrame = matrice_notes_gen """Les notes par UEs ou Compétences (DataFrame)""" self.matrice_coeffs_moy_gen: pd.DataFrame = matrice_coeffs """Les coeffs à appliquer pour le calcul des moyennes générales (toutes UE ou compétences confondues). NaN si étudiant non inscrit""" self.moyennes_gen: dict[int, pd.DataFrame] = {} """Dataframes retraçant les moyennes/classements/statistiques des étudiants aux UEs""" self.etudids = self.matrice_notes_gen.index """Les étudids renseignés dans les moyennes""" self.champs = self.matrice_notes_gen.columns """Les champs (acronymes d'UE ou compétences) renseignés dans les moyennes""" for col in self.champs: # if ue.type != UE_SPORT: # Les moyennes tous modules confondus notes = matrice_notes_gen[col] self.moyennes_gen[col] = pe_moy.Moyenne(notes) # Les moyennes générales (toutes UEs confondues) self.notes_gen = pd.Series(np.nan, index=self.matrice_notes_gen.index) if self.has_notes(): self.notes_gen = self.compute_moy_gen( self.matrice_notes_gen, self.matrice_coeffs_moy_gen ) self.moyenne_gen = pe_moy.Moyenne(self.notes_gen) """Dataframe retraçant les moyennes/classements/statistiques général (toutes UESs confondues et modules confondus)""" def has_notes(self): """Détermine si les moyennes (aux UEs ou aux compétences) ont des notes Returns: True si la moytag a des notes, False sinon """ notes = self.matrice_notes_gen nbre_nan = notes.isna().sum().sum() nbre_notes_potentielles = len(notes.index) * len(notes.columns) if nbre_nan == nbre_notes_potentielles: return False else: return True def compute_moy_gen(self, moys: pd.DataFrame, coeffs: pd.DataFrame) -> pd.Series: """Calcule la moyenne générale (toutes UE/compétences confondus) pour le tag considéré, en pondérant les notes obtenues au UE par les coeff (généralement les crédits ECTS). Args: moys: Les moyennes etudids x acronymes_ues/compétences coeff: Les coeff etudids x ueids/compétences """ # Calcule la moyenne générale dans le semestre (pondérée par le ECTS) try: moy_gen_tag = comp.moy_sem.compute_sem_moys_apc_using_ects( moys, coeffs.fillna(0.0), # formation_id=self.formsemestre.formation_id, skip_empty_ues=True, ) except TypeError as e: raise TypeError( "Pb dans le calcul de la moyenne toutes UEs/compétences confondues" ) return moy_gen_tag def to_df( self, aggregat=None, cohorte=None, options={"min_max_moy": True} ) -> pd.DataFrame: """Renvoie le df synthétisant l'ensemble des données connues Adapte les intitulés des colonnes aux données fournies (nom d'aggrégat, type de cohorte). """ if "min_max_moy" not in options or options["min_max_moy"]: with_min_max_moy = True else: with_min_max_moy = False etudids_sorted = sorted(self.etudids) df = pd.DataFrame(index=etudids_sorted) # Ajout des notes pour tous les champs champs = list(self.champs) for champ in champs: df_champ = self.moyennes_gen[champ].get_df_synthese( with_min_max_moy=with_min_max_moy ) # le dataframe # Renomme les colonnes cols = [ get_colonne_df(aggregat, self.tag, champ, cohorte, critere) for critere in pe_moy.Moyenne.get_colonnes_synthese( with_min_max_moy=with_min_max_moy ) ] df_champ.columns = cols df = df.join(df_champ) # Ajoute la moy générale df_moy_gen = self.moyenne_gen.get_df_synthese(with_min_max_moy=with_min_max_moy) cols = [ get_colonne_df(aggregat, self.tag, CHAMP_GENERAL, cohorte, critere) for critere in pe_moy.Moyenne.get_colonnes_synthese( with_min_max_moy=with_min_max_moy ) ] df_moy_gen.columns = cols df = df.join(df_moy_gen) return df def get_colonne_df(aggregat, tag, champ, cohorte, critere): """Renvoie le tuple (aggregat, tag, champ, cohorte, critere) utilisé pour désigner les colonnes du df""" liste_champs = [] if aggregat != None: liste_champs += [aggregat] liste_champs += [tag, champ] if cohorte != None: liste_champs += [cohorte] liste_champs += [critere] return "|".join(liste_champs)