forked from ScoDoc/ScoDoc
Optimize compute_module_moy
This commit is contained in:
parent
83ba9cf186
commit
5a3c25e67f
@ -121,8 +121,8 @@ def df_load_modimpl_notes(moduleimpl_id: int) -> pd.DataFrame:
|
||||
|
||||
|
||||
def compute_module_moy(
|
||||
evals_notes: pd.DataFrame,
|
||||
evals_poids: pd.DataFrame,
|
||||
evals_notes_df: pd.DataFrame,
|
||||
evals_poids_df: pd.DataFrame,
|
||||
evaluations: list,
|
||||
) -> pd.DataFrame:
|
||||
"""Calcule les moyennes des étudiants dans ce module
|
||||
@ -140,34 +140,35 @@ def compute_module_moy(
|
||||
ou NaN si les évaluations (dans lesquelles l'étudiant à des notes)
|
||||
ne donnent pas de coef vers cette UE.
|
||||
"""
|
||||
nb_etuds = len(evals_notes)
|
||||
nb_ues = evals_poids.shape[1]
|
||||
etud_moy_module_arr = np.zeros((nb_etuds, nb_ues))
|
||||
evals_poids_arr = evals_poids.to_numpy().transpose() * [
|
||||
e.coefficient for e in evaluations
|
||||
]
|
||||
# -> evals_poids_arr shape : (nb_ues, nb_evals)
|
||||
nb_etuds, nb_evals = evals_notes_df.shape
|
||||
nb_ues = evals_poids_df.shape[1]
|
||||
assert evals_poids_df.shape[0] == nb_evals # compat notes/poids
|
||||
evals_coefs = np.array([e.coefficient for e in evaluations], dtype=float).reshape(
|
||||
-1, 1
|
||||
)
|
||||
evals_poids = evals_poids_df.values * evals_coefs
|
||||
# -> evals_poids_arr shape : (nb_evals, nb_ues)
|
||||
assert evals_poids.shape == (nb_evals, nb_ues)
|
||||
# Remet les notes sur 20 (sauf notes spéciales <= -1000):
|
||||
evals_notes_arr = np.where(evals_notes.values > -1000, evals_notes.values, 0.0) / [
|
||||
e.note_max / 20.0 for e in evaluations
|
||||
]
|
||||
for i in range(nb_etuds):
|
||||
# note_vect: array [note_ue1, note_ue2, ...] de l'étudiant i
|
||||
note_vect = evals_notes_arr[i]
|
||||
# Les poids des évals pour cet étudiant: là où il a des notes non neutralisées
|
||||
# Attention: les NaN (codant les absents) sont remplacés par des 0 dans
|
||||
# evals_notes_arr mais pas dans evals_poids_etud_arr
|
||||
# (la comparaison est toujours false face à un NaN)
|
||||
evals_poids_etud_arr = np.where(
|
||||
evals_notes.values[i] <= -1000, 0, evals_poids_arr
|
||||
)
|
||||
# Calcule la moyenne pondérée sur les notes disponibles
|
||||
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
|
||||
etud_moy_module_arr[i] = (note_vect * evals_poids_etud_arr).sum(
|
||||
axis=1
|
||||
) / evals_poids_etud_arr.sum(axis=1)
|
||||
|
||||
evals_notes = np.where(
|
||||
evals_notes_df.values > -1000, evals_notes_df.values, 0.0
|
||||
) / [e.note_max / 20.0 for e in evaluations]
|
||||
# Les poids des évals pour les étudiant: là où il a des notes non neutralisées
|
||||
# Attention: les NaN (codant les absents) sont remplacés par des 0 dans
|
||||
# evals_notes_arr mais pas dans evals_poids_etuds_arr
|
||||
# (la comparaison est toujours false face à un NaN)
|
||||
# shape: (nb_etuds, nb_evals, nb_ues)
|
||||
poids_stacked = np.stack([evals_poids] * nb_etuds)
|
||||
evals_poids_etuds = np.where(
|
||||
np.stack([evals_notes_df.values] * nb_ues, axis=2) <= -1000.0, 0, poids_stacked
|
||||
)
|
||||
# Calcule la moyenne pondérée sur les notes disponibles
|
||||
evals_notes_stacked = np.stack([evals_notes] * nb_ues, axis=2)
|
||||
with np.errstate(invalid="ignore"): # ignore les 0/0 (-> NaN)
|
||||
etud_moy_module = np.sum(
|
||||
evals_poids_etuds * evals_notes_stacked, axis=1
|
||||
) / np.sum(evals_poids_etuds, axis=1)
|
||||
etud_moy_module_df = pd.DataFrame(
|
||||
etud_moy_module_arr, index=evals_notes.index, columns=evals_poids.columns
|
||||
etud_moy_module, index=evals_notes_df.index, columns=evals_poids_df.columns
|
||||
)
|
||||
return etud_moy_module_df
|
||||
|
@ -234,7 +234,7 @@ def test_module_moy_elem(test_client):
|
||||
"EVAL2": np.NaN, # et une ABS
|
||||
},
|
||||
]
|
||||
evals_notes = pd.DataFrame(
|
||||
evals_notes_df = pd.DataFrame(
|
||||
data, index=["etud1", "etud2", "etud3", "etud4", "etud5"]
|
||||
)
|
||||
# Poids des évaluations (1 ligne / évaluation)
|
||||
@ -242,13 +242,13 @@ def test_module_moy_elem(test_client):
|
||||
{"UE1": 1, "UE2": 0, "UE3": 0},
|
||||
{"UE1": 2, "UE2": 5, "UE3": 0},
|
||||
]
|
||||
evals_poids = pd.DataFrame(data, index=["EVAL1", "EVAL2"], dtype=float)
|
||||
evals_poids_df = pd.DataFrame(data, index=["EVAL1", "EVAL2"], dtype=float)
|
||||
evaluations = [
|
||||
Evaluation(note_max=20.0, coefficient=1.0),
|
||||
Evaluation(note_max=20.0, coefficient=1.0),
|
||||
]
|
||||
etud_moy_module_df = moy_mod.compute_module_moy(
|
||||
evals_notes.fillna(0.0), evals_poids, evaluations
|
||||
evals_notes_df.fillna(0.0), evals_poids_df, evaluations
|
||||
)
|
||||
NAN = 666.0 # pour pouvoir comparer NaN et NaN (car NaN != NaN)
|
||||
r = etud_moy_module_df.fillna(NAN)
|
||||
|
Loading…
Reference in New Issue
Block a user