2020-09-26 16:19:37 +02:00
|
|
|
# -*- mode: python -*-
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
##############################################################################
|
|
|
|
#
|
|
|
|
# Gestion scolarite IUT
|
|
|
|
#
|
2023-12-31 23:04:06 +01:00
|
|
|
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
|
2020-09-26 16:19:37 +02:00
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#
|
|
|
|
# Emmanuel Viennet emmanuel.viennet@viennet.net
|
|
|
|
#
|
|
|
|
##############################################################################
|
|
|
|
|
|
|
|
##############################################################################
|
|
|
|
# Module "Avis de poursuite d'étude"
|
|
|
|
# conçu et développé par Cléo Baras (IUT de Grenoble)
|
|
|
|
##############################################################################
|
|
|
|
|
|
|
|
"""
|
|
|
|
Created on Fri Sep 9 09:15:05 2016
|
|
|
|
|
|
|
|
@author: barasc
|
|
|
|
"""
|
2024-02-02 17:16:07 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
from app.pe import pe_affichage, pe_comp
|
|
|
|
import app.pe.pe_ressemtag as pe_ressemtag
|
2024-02-15 17:05:03 +01:00
|
|
|
import pandas as pd
|
|
|
|
import numpy as np
|
2020-09-26 16:19:37 +02:00
|
|
|
|
2024-02-15 17:05:03 +01:00
|
|
|
from app.pe.pe_tabletags import TableTag
|
|
|
|
from app.pe.pe_moytag import MoyennesTag
|
2024-02-19 14:50:38 +01:00
|
|
|
import app.pe.rcss.pe_rcf as pe_rcf
|
2020-09-26 16:19:37 +02:00
|
|
|
|
2024-02-08 22:09:11 +01:00
|
|
|
|
2024-02-17 02:35:43 +01:00
|
|
|
class SxTag(TableTag):
|
2024-02-19 14:50:38 +01:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
sxtag_id: (str, int),
|
|
|
|
rcf: pe_rcf.RCF,
|
|
|
|
ressembuttags: dict[int, pe_ressemtag.ResSemBUTTag],
|
|
|
|
):
|
2024-02-17 02:35:43 +01:00
|
|
|
"""Calcule les moyennes/classements par tag d'un semestre de type 'Sx'
|
2024-02-18 19:24:03 +01:00
|
|
|
(par ex. 'S1', 'S2', ...) avec une orientation par UE :
|
2024-02-15 17:05:03 +01:00
|
|
|
|
|
|
|
* pour les étudiants non redoublants, ce sont les moyennes/classements
|
|
|
|
du semestre suivi
|
|
|
|
* pour les étudiants redoublants, c'est une fusion des moyennes/classements
|
2024-02-17 02:35:43 +01:00
|
|
|
dans les (2) 'Sx' qu'il a suivi
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-17 02:35:43 +01:00
|
|
|
Un SxTag peut donc regrouper plusieurs semestres.
|
|
|
|
|
|
|
|
Un SxTag est identifié par un tuple (x, fid) où x est le numéro (semestre_id)
|
|
|
|
du semestre et fid le formsemestre_id du semestre final (le plus récent) du
|
|
|
|
regrouprement.
|
|
|
|
|
|
|
|
Les **tags**, les **UE** et les inscriptions aux UEs (pour les etudiants)
|
|
|
|
considérés sont uniquement ceux du semestre final.
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-01-20 16:34:38 +01:00
|
|
|
Args:
|
2024-02-17 02:35:43 +01:00
|
|
|
sxtag_id: L'identifiant de SxTag
|
|
|
|
ressembuttags: Un dictionnaire de la forme `{fid: ResSemBUTTag(fid)}` donnant
|
|
|
|
les semestres à regrouper et les résultats/moyennes par tag des
|
|
|
|
semestres
|
2020-09-26 16:19:37 +02:00
|
|
|
"""
|
2024-01-27 09:15:17 +01:00
|
|
|
TableTag.__init__(self)
|
2024-01-25 17:17:01 +01:00
|
|
|
|
2024-02-17 03:30:19 +01:00
|
|
|
assert sxtag_id and len(sxtag_id) == 2 and sxtag_id[1] in ressembuttags
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
self.sxtag_id: (str, int) = sxtag_id
|
|
|
|
"""Identifiant du SxTag de la forme (nom_Sx, fid_semestre_final)"""
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
self.rcf = rcf
|
|
|
|
"""Le RCF sur lequel il s'appuie"""
|
|
|
|
|
|
|
|
# Les resultats des semestres taggués à prendre en compte dans le RCF
|
|
|
|
self.ressembuttags = {fid: ressembuttags[fid] for fid in rcf.semestres_aggreges}
|
2024-02-17 02:35:43 +01:00
|
|
|
"""Les ResSemBUTTags à regrouper dans le SxTag"""
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-17 02:35:43 +01:00
|
|
|
# Les données du semestre final
|
|
|
|
self.fid_final = sxtag_id[1]
|
|
|
|
self.ressembuttag_final = ressembuttags[self.fid_final]
|
|
|
|
"""Le ResSemBUTTag final"""
|
2024-02-16 16:07:48 +01:00
|
|
|
|
2024-02-17 02:35:43 +01:00
|
|
|
self.etuds = ressembuttags[self.fid_final].etuds
|
2024-02-19 14:50:38 +01:00
|
|
|
"""Les étudiants du ReSemBUTTag final"""
|
|
|
|
|
|
|
|
# Ajout les etudids et les états civils
|
2024-02-17 02:35:43 +01:00
|
|
|
self.add_etuds(self.etuds)
|
2024-02-19 14:50:38 +01:00
|
|
|
self.etudids_sorted = sorted(self.etudids)
|
|
|
|
"""Les etudids triés"""
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-18 19:24:03 +01:00
|
|
|
# Affichage
|
2024-02-17 03:30:19 +01:00
|
|
|
pe_affichage.pe_print(f"--> {self.get_repr()}")
|
|
|
|
|
2024-02-15 17:05:03 +01:00
|
|
|
# Les tags
|
2024-02-17 02:35:43 +01:00
|
|
|
self.tags_sorted = self.ressembuttag_final.tags_sorted
|
|
|
|
"""Tags (extraits uniquement du semestre final)"""
|
|
|
|
pe_affichage.pe_print(f"* Tags : {', '.join(self.tags_sorted)}")
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-17 02:35:43 +01:00
|
|
|
# Les UE
|
2024-02-18 19:24:03 +01:00
|
|
|
moy_sem_final = self.ressembuttag_final.moyennes_tags["but"]
|
|
|
|
self.ues = list(moy_sem_final.matrice_notes.columns)
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
# L'association UE-compétences extraites du dernier semestre
|
|
|
|
self.competences = self.ressembuttag_final.competences
|
|
|
|
|
2024-02-17 02:35:43 +01:00
|
|
|
# Les acronymes des UE
|
2024-02-18 19:24:03 +01:00
|
|
|
self.acronymes_ues_sorted = sorted(self.ues)
|
2024-02-16 16:07:48 +01:00
|
|
|
|
2024-02-17 02:35:43 +01:00
|
|
|
# Les inscriptions des étudiants aux UEs
|
|
|
|
# => ne conserve que les UEs du semestre final (pour les redoublants)
|
2024-02-19 14:50:38 +01:00
|
|
|
self.ues_inscr_parcours_df = self.ressembuttag_final.ues_inscr_parcours_df
|
|
|
|
self.ues_inscr_parcours_df.sort_index()
|
2024-02-18 19:24:03 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
# Les coeffs pour la moyenne générale
|
|
|
|
self.matrice_coeffs_moy_gen = self.ressembuttag_final.moyennes_tags[
|
|
|
|
"but"
|
|
|
|
].matrice_coeffs_moy_gen
|
|
|
|
self.matrice_coeffs_moy_gen.sort_index() # Trie les coeff par etudids
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-17 02:35:43 +01:00
|
|
|
# Les moyennes par tag
|
2024-02-16 16:07:48 +01:00
|
|
|
self.moyennes_tags: dict[str, pd.DataFrame] = {}
|
|
|
|
"""Les notes aux UEs dans différents tags"""
|
2024-02-17 02:35:43 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
# Masque des inscriptions et des capitalisations
|
|
|
|
self.masque_df, masque_cube = compute_masques_ues_cube(
|
|
|
|
self.etudids_sorted,
|
|
|
|
self.acronymes_ues_sorted,
|
|
|
|
self.ressembuttags,
|
|
|
|
self.fid_final,
|
|
|
|
)
|
2024-02-19 20:00:11 +01:00
|
|
|
self._aff_capitalisations()
|
2024-02-19 14:50:38 +01:00
|
|
|
|
2024-02-15 17:05:03 +01:00
|
|
|
for tag in self.tags_sorted:
|
2024-02-19 20:00:11 +01:00
|
|
|
# Y-a-t-il des notes ?
|
|
|
|
if not self.has_notes(tag):
|
|
|
|
pe_affichage.pe_print(f"> MoyTag 🏷{tag} actuellement sans ◯ notes")
|
|
|
|
matrice_moys_ues = pd.DataFrame(np.nan, index=self.etudids_sorted, columns=self.acronymes_ues_sorted)
|
|
|
|
|
|
|
|
else:
|
|
|
|
# Cube de note etudids x UEs
|
|
|
|
notes_df, notes_cube = compute_notes_ues_cube(
|
|
|
|
tag,
|
|
|
|
self.etudids_sorted,
|
|
|
|
self.acronymes_ues_sorted,
|
|
|
|
self.ressembuttags,
|
|
|
|
)
|
2024-02-19 14:50:38 +01:00
|
|
|
|
2024-02-19 20:00:11 +01:00
|
|
|
# self.ues_inscr_parcours = ~np.isnan(self.matrice_coeffs.to_numpy())
|
|
|
|
# inscr_mask = self.ues_inscr_parcours
|
|
|
|
|
|
|
|
# Calcule des moyennes sous forme d'un dataframe
|
|
|
|
inscr_mask = ~np.isnan(self.ues_inscr_parcours_df.to_numpy())
|
|
|
|
matrice_moys_ues: pd.DataFrame = compute_notes_ues(
|
|
|
|
notes_cube,
|
|
|
|
masque_cube,
|
|
|
|
self.etudids_sorted,
|
|
|
|
self.acronymes_ues_sorted,
|
|
|
|
inscr_mask,
|
|
|
|
)
|
2024-02-19 14:50:38 +01:00
|
|
|
|
2024-02-19 20:00:11 +01:00
|
|
|
# Les profils d'ects (pour debug)
|
|
|
|
profils_ects = []
|
|
|
|
for i in self.matrice_coeffs_moy_gen.index:
|
|
|
|
val = tuple(self.matrice_coeffs_moy_gen.loc[i].fillna("x"))
|
|
|
|
if tuple(val) not in profils_ects:
|
|
|
|
profils_ects.append(tuple(val))
|
|
|
|
pe_affichage.pe_print(
|
|
|
|
f"> MoyTag 🏷{tag} avec "
|
|
|
|
+ f"ues={self.acronymes_ues_sorted} "
|
|
|
|
+ f"ects={profils_ects}"
|
|
|
|
)
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-19 20:00:11 +01:00
|
|
|
# Les moyennes au tag
|
|
|
|
self.moyennes_tags[tag] = MoyennesTag(
|
|
|
|
tag, matrice_moys_ues, self.matrice_coeffs_moy_gen
|
|
|
|
)
|
2024-02-19 14:50:38 +01:00
|
|
|
|
2024-02-18 19:24:03 +01:00
|
|
|
|
2024-02-19 20:00:11 +01:00
|
|
|
def has_notes(self, tag):
|
|
|
|
"""Détermine si le SxTag, pour un tag donné, est en cours d'évaluation.
|
|
|
|
Si oui, n'a pas (encore) de notes dans le resformsemestre final.
|
2024-02-18 19:24:03 +01:00
|
|
|
|
2024-02-19 20:00:11 +01:00
|
|
|
Args:
|
|
|
|
tag: Le tag visé
|
2024-02-18 19:24:03 +01:00
|
|
|
|
2024-02-19 20:00:11 +01:00
|
|
|
Returns:
|
|
|
|
True si a des notes, False sinon
|
|
|
|
"""
|
|
|
|
moy_tag_dernier_sem = self.ressembuttag_final.moyennes_tags[tag]
|
|
|
|
notes = moy_tag_dernier_sem.matrice_notes
|
|
|
|
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
|
2024-02-15 17:05:03 +01:00
|
|
|
|
|
|
|
def __eq__(self, other):
|
2024-02-17 02:35:43 +01:00
|
|
|
"""Egalité de 2 SxTag sur la base de leur identifiant"""
|
|
|
|
return self.sxtag_id == other.sxtag_id
|
2024-02-15 17:05:03 +01:00
|
|
|
|
|
|
|
def get_repr(self, verbose=False) -> str:
|
|
|
|
"""Renvoie une représentation textuelle (celle de la trajectoire sur laquelle elle
|
|
|
|
est basée)"""
|
2024-02-19 14:50:38 +01:00
|
|
|
if verbose:
|
|
|
|
return f"{self.sxtag_id[0]}Tag basé sur {self.rcf.get_repr()}"
|
|
|
|
else:
|
|
|
|
# affichage = [str(fid) for fid in self.ressembuttags]
|
|
|
|
return f"{self.sxtag_id[0]}Tag (#{self.fid_final})"
|
2024-02-15 17:05:03 +01:00
|
|
|
|
2024-02-19 20:00:11 +01:00
|
|
|
def _aff_capitalisations(self):
|
|
|
|
"""Affichage des capitalisations du sxtag pour debug"""
|
|
|
|
for etud in self.etuds:
|
|
|
|
cap = []
|
|
|
|
for frmsem_id in self.ressembuttags:
|
|
|
|
if frmsem_id != self.fid_final:
|
|
|
|
for accr in self.acronymes_ues_sorted:
|
|
|
|
if self.masque_df[frmsem_id].loc[etud.etudid, accr] > 0.0:
|
|
|
|
cap += [accr]
|
|
|
|
if cap:
|
|
|
|
pe_affichage.pe_print(
|
|
|
|
f" ⚠ Capitalisation de {etud.etat_civil} : {', '.join(cap)}"
|
|
|
|
)
|
|
|
|
|
2020-09-26 16:19:37 +02:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
def compute_notes_ues_cube(
|
|
|
|
tag, etudids_sorted, acronymes_ues_sorted, ressembuttags
|
|
|
|
) -> (pd.DataFrame, np.array):
|
|
|
|
"""Construit le cube de notes des UEs (etudid x accronyme_ue x semestre_aggregé)
|
|
|
|
nécessaire au calcul des moyennes du tag pour le RCS Sx.
|
|
|
|
(Renvoie également le dataframe associé pour debug).
|
|
|
|
|
|
|
|
Args:
|
|
|
|
etudids_sorted: La liste des etudids triés par ordre croissant (dim 0)
|
|
|
|
acronymes_ues_sorted: La liste des acronymes de UEs triés par acronyme croissant (dim 1)
|
|
|
|
ressembuttags: Le dictionnaire des résultats de semestres BUT (tous tags confondus)
|
|
|
|
"""
|
|
|
|
# Index du cube (etudids -> dim 0, ues -> dim 1, semestres -> dim2)
|
|
|
|
# etudids_sorted = etudids_sorted
|
|
|
|
# acronymes_ues = sorted([ue.acronyme for ue in selMf.ues.values()])
|
|
|
|
semestres_id = list(ressembuttags.keys())
|
|
|
|
|
|
|
|
dfs = {}
|
|
|
|
|
|
|
|
for frmsem_id in semestres_id:
|
|
|
|
# Partant d'un dataframe vierge
|
|
|
|
df = pd.DataFrame(np.nan, index=etudids_sorted, columns=acronymes_ues_sorted)
|
|
|
|
|
|
|
|
# Charge les notes du semestre tag
|
|
|
|
sem_tag = ressembuttags[frmsem_id]
|
|
|
|
moys_tag = sem_tag.moyennes_tags[tag]
|
|
|
|
notes = moys_tag.matrice_notes # dataframe etudids x ues
|
2024-01-20 16:34:38 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
# les étudiants et les acronymes communs
|
|
|
|
etudids_communs, acronymes_communs = pe_comp.find_index_and_columns_communs(
|
|
|
|
df, notes
|
|
|
|
)
|
2024-01-20 16:34:38 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
# Recopie
|
|
|
|
df.loc[etudids_communs, acronymes_communs] = notes.loc[
|
|
|
|
etudids_communs, acronymes_communs
|
|
|
|
]
|
|
|
|
|
|
|
|
# Supprime tout ce qui n'est pas numérique
|
|
|
|
for col in df.columns:
|
|
|
|
df[col] = pd.to_numeric(df[col], errors="coerce")
|
|
|
|
|
|
|
|
# Stocke le df
|
|
|
|
dfs[frmsem_id] = df
|
|
|
|
|
|
|
|
"""Réunit les notes sous forme d'un cube etudids x ues x semestres"""
|
|
|
|
semestres_x_etudids_x_ues = [dfs[fid].values for fid in dfs]
|
|
|
|
etudids_x_ues_x_semestres = np.stack(semestres_x_etudids_x_ues, axis=-1)
|
|
|
|
return dfs, etudids_x_ues_x_semestres
|
|
|
|
|
|
|
|
|
|
|
|
def compute_masques_ues_cube(
|
|
|
|
etudids_sorted: list[int],
|
|
|
|
acronymes_ues_sorted: list[str],
|
|
|
|
ressembuttags: dict[int, pe_ressemtag.ResSemBUTTag],
|
|
|
|
formsemestre_id_final: int,
|
|
|
|
) -> (pd.DataFrame, np.array):
|
|
|
|
"""Construit le cube traduisant le masque des UEs à prendre en compte dans le calcul
|
|
|
|
des moyennes, en utilisant le df capitalisations de chaque ResSemBUTTag
|
|
|
|
|
|
|
|
Ce masque contient : 1 si la note doit être prise en compte ; 0 sinon
|
|
|
|
|
|
|
|
Args:
|
|
|
|
etudids_sorted: La liste des etudids triés par ordre croissant (dim 0)
|
|
|
|
acronymes_ues_sorted: La liste des acronymes de UEs triés par acronyme croissant (dim 1)
|
|
|
|
# ues_inscr_parcours_df: Le dataFrame des inscriptions au UE en fonction du parcours
|
|
|
|
ressembuttags: Le dictionnaire des résultats de semestres BUT (tous tags confondus)
|
|
|
|
formsemestre_id_final: L'identifiant du formsemestre_id_final (dont il faut forcément prendre en compte les coeffs)
|
|
|
|
"""
|
|
|
|
# Index du cube (etudids -> dim 0, ues -> dim 1, semestres -> dim2)
|
|
|
|
# etudids_sorted = etudids_sorted
|
|
|
|
# acronymes_ues = sorted([ue.acronyme for ue in selMf.ues.values()])
|
|
|
|
semestres_id = list(ressembuttags.keys())
|
|
|
|
|
|
|
|
dfs = {}
|
|
|
|
|
|
|
|
for frmsem_id in semestres_id:
|
|
|
|
# Partant d'un dataframe contenant des 1.0
|
|
|
|
if frmsem_id == formsemestre_id_final:
|
|
|
|
df = pd.DataFrame(1.0, index=etudids_sorted, columns=acronymes_ues_sorted)
|
2024-02-19 20:00:11 +01:00
|
|
|
else: # semestres redoublés
|
2024-02-19 14:50:38 +01:00
|
|
|
df = pd.DataFrame(0.0, index=etudids_sorted, columns=acronymes_ues_sorted)
|
|
|
|
|
|
|
|
# Traitement des capitalisations
|
|
|
|
capitalisations = ressembuttags[frmsem_id].capitalisations
|
|
|
|
capitalisations = capitalisations.replace(True, 1.0).replace(False, 0.0)
|
|
|
|
|
|
|
|
# Met à 0 les coeffs des UEs non capitalisées : 1.0*False => 0.0
|
|
|
|
etudids_communs, acronymes_communs = pe_comp.find_index_and_columns_communs(
|
|
|
|
df, capitalisations
|
|
|
|
)
|
|
|
|
|
|
|
|
df.loc[etudids_communs, acronymes_communs] = capitalisations.loc[
|
|
|
|
etudids_communs, acronymes_communs
|
|
|
|
]
|
|
|
|
|
|
|
|
# Stocke le df
|
|
|
|
dfs[frmsem_id] = df
|
|
|
|
|
|
|
|
"""Réunit les notes sous forme d'un cube etudids x ues x semestres"""
|
|
|
|
semestres_x_etudids_x_ues = [dfs[fid].values for fid in dfs]
|
|
|
|
etudids_x_ues_x_semestres = np.stack(semestres_x_etudids_x_ues, axis=-1)
|
|
|
|
return dfs, etudids_x_ues_x_semestres
|
2024-01-20 16:34:38 +01:00
|
|
|
|
|
|
|
|
2024-02-16 16:07:48 +01:00
|
|
|
def compute_notes_ues(
|
|
|
|
set_cube: np.array,
|
2024-02-19 14:50:38 +01:00
|
|
|
masque_cube: np.array,
|
|
|
|
etudids_sorted: list,
|
|
|
|
acronymes_ues_sorted: list,
|
2024-02-16 16:07:48 +01:00
|
|
|
inscr_mask: np.array,
|
|
|
|
):
|
2024-02-15 17:05:03 +01:00
|
|
|
"""Calcule la moyenne par UEs à un tag donné en prenant la note maximum (UE
|
|
|
|
par UE) obtenue par un étudiant à un semestre.
|
2024-01-20 16:34:38 +01:00
|
|
|
|
2024-02-15 17:05:03 +01:00
|
|
|
Args:
|
|
|
|
set_cube: notes moyennes aux modules ndarray
|
|
|
|
(semestre_ids x etudids x UEs), des floats avec des NaN
|
2024-02-19 14:50:38 +01:00
|
|
|
masque_cube: masque indiquant si la note doit être prise en compte ndarray
|
|
|
|
(semestre_ids x etudids x UEs), des 1.0 ou des 0.0
|
|
|
|
etudids_sorted: liste des étudiants (dim. 0 du cube) trié par etudid
|
|
|
|
acronymes_ues_sorted: liste des acronymes des ues (dim. 1 du cube) trié par acronyme
|
2024-02-16 16:07:48 +01:00
|
|
|
inscr_mask: masque etudids x UE traduisant les inscriptions des
|
|
|
|
étudiants aux UE (du semestre terminal)
|
2024-02-15 17:05:03 +01:00
|
|
|
Returns:
|
|
|
|
Un DataFrame avec pour columns les moyennes par ues,
|
|
|
|
et pour rows les etudid
|
|
|
|
"""
|
|
|
|
nb_etuds, nb_ues, nb_semestres = set_cube.shape
|
2024-02-16 16:07:48 +01:00
|
|
|
nb_etuds_mask, nb_ues_mask = inscr_mask.shape
|
2024-02-19 14:50:38 +01:00
|
|
|
assert nb_etuds == len(etudids_sorted)
|
|
|
|
assert nb_ues == len(acronymes_ues_sorted)
|
2024-02-16 16:07:48 +01:00
|
|
|
assert nb_etuds == nb_etuds_mask
|
|
|
|
assert nb_ues == nb_ues_mask
|
2024-01-20 16:34:38 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
# Entrées à garder dans le cube en fonction du masque d'inscription aux UEs du parcours
|
2024-02-17 02:35:43 +01:00
|
|
|
inscr_mask_3D = np.stack([inscr_mask] * nb_semestres, axis=-1)
|
|
|
|
set_cube = set_cube * inscr_mask_3D
|
2024-02-16 16:07:48 +01:00
|
|
|
|
2024-02-19 14:50:38 +01:00
|
|
|
# Entrées à garder en fonction des UEs capitalisées ou non
|
|
|
|
set_cube = set_cube * masque_cube
|
|
|
|
|
|
|
|
# Quelles entrées du cube contiennent des notes ?
|
|
|
|
mask = ~np.isnan(set_cube)
|
|
|
|
|
2024-02-16 16:07:48 +01:00
|
|
|
# Enlève les NaN du cube pour les entrées manquantes : NaN -> -1.0
|
2024-02-15 17:05:03 +01:00
|
|
|
set_cube_no_nan = np.nan_to_num(set_cube, nan=-1.0)
|
2024-02-02 17:16:07 +01:00
|
|
|
|
2024-02-15 17:05:03 +01:00
|
|
|
# Les moyennes par ues
|
|
|
|
# TODO: Pour l'instant un max sans prise en compte des UE capitalisées
|
|
|
|
etud_moy = np.max(set_cube_no_nan, axis=2)
|
2024-02-02 17:16:07 +01:00
|
|
|
|
2024-02-15 17:05:03 +01:00
|
|
|
# Fix les max non calculé -1 -> NaN
|
|
|
|
etud_moy[etud_moy < 0] = np.NaN
|
2024-02-02 17:16:07 +01:00
|
|
|
|
2024-02-15 17:05:03 +01:00
|
|
|
# Le dataFrame
|
|
|
|
etud_moy_tag_df = pd.DataFrame(
|
|
|
|
etud_moy,
|
2024-02-19 14:50:38 +01:00
|
|
|
index=etudids_sorted, # les etudids
|
|
|
|
columns=acronymes_ues_sorted, # les tags
|
2024-02-15 17:05:03 +01:00
|
|
|
)
|
2024-02-08 22:09:11 +01:00
|
|
|
|
2024-02-15 17:05:03 +01:00
|
|
|
etud_moy_tag_df.fillna(np.nan)
|
2024-02-02 17:16:07 +01:00
|
|
|
|
2024-02-15 17:05:03 +01:00
|
|
|
return etud_moy_tag_df
|