From 09ac9f01f82d7925a99c0c70e0ce44840f12d0ed Mon Sep 17 00:00:00 2001 From: Bertrand Benjamin Date: Fri, 15 Jan 2021 13:48:57 +0100 Subject: [PATCH] Feat: add competence fig and better error management --- recopytex/dashboard/exam.py | 155 +++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 62 deletions(-) diff --git a/recopytex/dashboard/exam.py b/recopytex/dashboard/exam.py index 866eeee..5c3026c 100644 --- a/recopytex/dashboard/exam.py +++ b/recopytex/dashboard/exam.py @@ -75,7 +75,7 @@ app.layout = html.Div( columns=[ {"id": "Élève", "name": "Élève"}, {"id": "Note", "name": "Note"}, - {"id": "Barème", "name": "Bareme"}, + {"id": "Barème", "name": "Barème"}, ], data=[], style_data_conditional=[ @@ -99,11 +99,21 @@ app.layout = html.Div( [ dash_table.DataTable( id="final_score_describe", + columns=[{"id": "count", "name": "count"}, + {"id": "mean", "name": "mean"}, + {"id": "std", "name": "std"}, + {"id": "min", "name": "min"}, + {"id": "25%", "name": "25%"}, + {"id": "50%", "name": "50%"}, + {"id": "75%", "name": "75%"}, + {"id": "max", "name": "max"}, + ] + ), dcc.Graph( id="fig_assessment_hist", ), - # dcc.Graph(id="fig_competences"), + dcc.Graph(id="fig_competences"), ] ), ], @@ -156,42 +166,47 @@ def update_csvs(value): def update_final_scores(data): if not data: raise PreventUpdate + + scores = pd.DataFrame.from_records(data) try: - scores = pd.DataFrame.from_records(data) - scores = flat_df_students(scores).dropna(subset=["Score"]) - scores = pp_q_scores(scores) - assessment_scores = scores.groupby(["Eleve"]).agg( - {"Note": "sum", "Bareme": "sum"} - ) - return [assessment_scores.reset_index().to_dict("records")] + if scores.iloc[0]["Commentaire"] == "commentaire": + scores.drop([0], inplace=True) except KeyError: - raise PreventUpdate + pass + scores = flat_df_students(scores).dropna(subset=["Score"]) + if scores.empty: + return [{}] + + scores = pp_q_scores(scores) + assessment_scores = scores.groupby(["Eleve"]).agg( + {"Note": "sum", "Bareme": "sum"} + ) + return [assessment_scores.reset_index().to_dict("records")] @app.callback( [ - dash.dependencies.Output("final_score_table", "columns"), dash.dependencies.Output("final_score_table", "data"), ], [dash.dependencies.Input("final_score", "data")], ) def update_final_scores_table(data): assessment_scores = pd.DataFrame.from_records(data) - return [ - {"id": c, "name": c} for c in assessment_scores.columns - ], assessment_scores.to_dict("records") + return [assessment_scores.to_dict("records")] @app.callback( [ - dash.dependencies.Output("final_score_describe", "columns"), dash.dependencies.Output("final_score_describe", "data"), ], [dash.dependencies.Input("final_score", "data")], ) def update_final_scores_descr(data): - desc = pd.DataFrame.from_records(data)["Note"].describe() - return [{"id": c, "name": c} for c in desc.keys()], [desc.to_dict()] + scores = pd.DataFrame.from_records(data) + if scores.empty: + return [[{}]] + desc = scores["Note"].describe().T + return [[desc.to_dict()]] @app.callback( @@ -203,6 +218,9 @@ def update_final_scores_descr(data): def update_final_scores_hist(data): assessment_scores = pd.DataFrame.from_records(data) + if assessment_scores.empty: + return [{}] + ranges = np.linspace( 0, assessment_scores.Bareme.max(), int(assessment_scores.Bareme.max() * 2 + 1) ) @@ -230,51 +248,64 @@ def update_final_scores_hist(data): return [fig] -# @app.callback( -# [ -# dash.dependencies.Output("fig_competences", "figure"), -# ], -# [dash.dependencies.Input("scores_table", "data")], -# ) -# def update_competence_fig(data): -# scores = pd.DataFrame.from_records(data) -# scores = flat_df_students(scores).dropna(subset=["Score"]) -# scores = pp_q_scores(scores) -# pt = pd.pivot_table( -# scores, -# index=["Exercice", "Question", "Commentaire"], -# columns="Score", -# aggfunc="size", -# fill_value=0, -# ) -# for i in {i for i in pt.index.get_level_values(0)}: -# pt.loc[(str(i), "", ""), :] = "" -# pt.sort_index(inplace=True) -# index = ( -# pt.index.get_level_values(0) -# + ":" -# + pt.index.get_level_values(1) -# + " " -# + pt.index.get_level_values(2) -# ) -# -# fig = go.Figure() -# bars = [ -# {"score": -1, "name": "Pas de réponse", "color": COLORS["."]}, -# {"score": 0, "name": "Faut", "color": COLORS[0]}, -# {"score": 1, "name": "Peu juste", "color": COLORS[1]}, -# {"score": 2, "name": "Presque juste", "color": COLORS[2]}, -# {"score": 3, "name": "Juste", "color": COLORS[3]}, -# ] -# for b in bars: -# try: -# fig.add_bar( -# x=index, y=pt[b["score"]], name=b["name"], marker_color=b["color"] -# ) -# except KeyError: -# pass -# fig.update_layout(barmode="relative") -# return [fig] +@app.callback( + [ + dash.dependencies.Output("fig_competences", "figure"), + ], + [dash.dependencies.Input("scores_table", "data")], +) +def update_competence_fig(data): + scores = pd.DataFrame.from_records(data) + try: + if scores.iloc[0]["Commentaire"] == "commentaire": + scores.drop([0], inplace=True) + except KeyError: + pass + scores = flat_df_students(scores).dropna(subset=["Score"]) + + if scores.empty: + return [{}] + + scores = pp_q_scores(scores) + pt = pd.pivot_table( + scores, + index=["Exercice", "Question", "Commentaire"], + columns="Score", + aggfunc="size", + fill_value=0, + ) + for i in {i for i in pt.index.get_level_values(0)}: + pt.loc[(str(i), "", ""), :] = "" + pt.sort_index(inplace=True) + index = ( + pt.index.get_level_values(0) + + ":" + + pt.index.get_level_values(1) + + " " + + pt.index.get_level_values(2) + ) + + fig = go.Figure() + bars = [ + {"score": -1, "name": "Pas de réponse", "color": COLORS["."]}, + {"score": 0, "name": "Faut", "color": COLORS[0]}, + {"score": 1, "name": "Peu juste", "color": COLORS[1]}, + {"score": 2, "name": "Presque juste", "color": COLORS[2]}, + {"score": 3, "name": "Juste", "color": COLORS[3]}, + ] + for b in bars: + try: + fig.add_bar( + x=index, y=pt[b["score"]], name=b["name"], marker_color=b["color"] + ) + except KeyError: + pass + fig.update_layout(barmode="relative") + fig.update_layout( + height=500, + margin=dict(l=5, r=5, b=5, t=5), + ) + return [fig] @app.callback(