Feat: Hist graph and describe

This commit is contained in:
Bertrand Benjamin 2021-01-12 22:32:26 +01:00
parent cfd5928853
commit f6bfac4144

View File

@ -6,9 +6,11 @@ import dash_html_components as html
import dash_core_components as dcc import dash_core_components as dcc
import dash_table import dash_table
from dash.exceptions import PreventUpdate from dash.exceptions import PreventUpdate
import plotly.graph_objects as go
from pathlib import Path from pathlib import Path
from datetime import datetime from datetime import datetime
import pandas as pd import pandas as pd
import numpy as np
from .. import flat_df_students, pp_q_scores from .. import flat_df_students, pp_q_scores
@ -23,55 +25,94 @@ COLORS = {
3: "#68D42F", 3: "#68D42F",
} }
app = dash.Dash(__name__) external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# app = dash.Dash(__name__)
app.layout = html.Div([ app.layout = html.Div(
[
html.H1("Analyse des notes"), html.H1("Analyse des notes"),
html.Div(["Classe: ", dcc.Dropdown( html.Div(
id='tribe', [
options=[{"label": t["name"], "value": t["name"]} for t in config["tribes"]], "Classe: ",
dcc.Dropdown(
id="tribe",
options=[
{"label": t["name"], "value": t["name"]}
for t in config["tribes"]
],
value=config["tribes"][0]["name"], value=config["tribes"][0]["name"],
)]), ),
html.Div(["Evaluation: ", dcc.Dropdown(id='csv')]), "Evaluation: ",
html.Div([dash_table.DataTable( dcc.Dropdown(id="csv"),
],
style={"columnCount": 2},
),
html.Div(
[
dash_table.DataTable(
id="final_score_table", id="final_score_table",
columns = [{"id": "Élève", "name": "Élève"}, {"id": "Note", "name": "Note"},{"id": "Barème", "name": "Bareme"}], columns=[
{"id": "Élève", "name": "Élève"},
{"id": "Note", "name": "Note"},
{"id": "Barème", "name": "Bareme"},
],
data=[], data=[],
style_data_conditional=[ style_data_conditional=[
{ {
'if': {'row_index': 'odd'}, "if": {"row_index": "odd"},
'backgroundColor': 'rgb(248, 248, 248)' "backgroundColor": "rgb(248, 248, 248)",
} }
], ],
style_header={ style_header={
'backgroundColor': 'rgb(230, 230, 230)', "backgroundColor": "rgb(230, 230, 230)",
'fontWeight': 'bold' "fontWeight": "bold",
}, },
style_data={ style_data={
'width': '100px', "width": "100px",
'maxWidth': '100px', "maxWidth": "100px",
'minWidth': '100px', "minWidth": "100px",
}, },
), ),
]), html.Div(
[
dash_table.DataTable(
id="final_score_describe",
),
dcc.Graph(id="fig_assessment_hist"),
]
),
],
style={"columnCount": 2},
),
html.Br(), html.Br(),
html.Div([dash_table.DataTable( html.Div(
[
dash_table.DataTable(
id="scores_table", id="scores_table",
columns = [{"id": c, "name":c} for c in NO_ST_COLUMNS.values()], columns=[{"id": c, "name": c} for c in NO_ST_COLUMNS.values()],
style_cell={ style_cell={
'whiteSpace': 'normal', "whiteSpace": "normal",
'height': 'auto', "height": "auto",
}, },
style_data_conditional=[], style_data_conditional=[],
editable=True, editable=True,
)]), )
]
),
html.P(id="lastsave"), html.P(id="lastsave"),
]) dcc.Store(id="final_score"),
]
)
@app.callback( @app.callback(
[dash.dependencies.Output("csv", "options"), dash.dependencies.Output("csv", "value")], [
dash.dependencies.Output("csv", "options"),
dash.dependencies.Output("csv", "value"),
],
[dash.dependencies.Input("tribe", "value")], [dash.dependencies.Input("tribe", "value")],
) )
def update_csvs(value): def update_csvs(value):
if not value: if not value:
raise PreventUpdate raise PreventUpdate
@ -82,26 +123,93 @@ def update_csvs(value):
except IndexError: except IndexError:
return [] return []
@app.callback( @app.callback(
[dash.dependencies.Output("final_score_table", "columns"), dash.dependencies.Output("final_score_table", "data")], [
dash.dependencies.Output("final_score", "data"),
],
[dash.dependencies.Input("scores_table", "data")], [dash.dependencies.Input("scores_table", "data")],
) )
def update_final_scores_table(data): def update_final_scores(data):
if not data: if not data:
raise PreventUpdate raise PreventUpdate
try: try:
scores = pd.DataFrame.from_records(data) scores = pd.DataFrame.from_records(data)
scores = flat_df_students(scores).dropna(subset=["Score"]) scores = flat_df_students(scores).dropna(subset=["Score"])
scores = pp_q_scores(scores) scores = pp_q_scores(scores)
assessment_scores = scores.groupby(["Eleve"]).agg({"Note": "sum", "Bareme": "sum"}) assessment_scores = scores.groupby(["Eleve"]).agg(
return [{"id": c, "name": c} for c in assessment_scores.reset_index().columns], assessment_scores.reset_index().to_dict('records') {"Note": "sum", "Bareme": "sum"}
)
return [assessment_scores.reset_index().to_dict("records")]
except KeyError: except KeyError:
raise PreventUpdate raise PreventUpdate
@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")
@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()
print(desc.keys())
return [{"id": c, "name": c} for c in desc.keys()], [desc.to_dict()]
@app.callback(
[
dash.dependencies.Output("fig_assessment_hist", "figure"),
],
[dash.dependencies.Input("final_score", "data")],
)
def update_final_scores_hist(data):
assessment_scores = pd.DataFrame.from_records(data)
ranges = np.linspace(
0, assessment_scores.Bareme.max(), int(assessment_scores.Bareme.max() * 2 + 1)
)
bins = pd.cut(assessment_scores["Note"], ranges)
assessment_scores["Bin"] = bins
assessment_grouped = (
assessment_scores.reset_index()
.groupby("Bin")
.agg({"Bareme": "count", "Eleve": lambda x: "\n".join(x)})
)
assessment_grouped.index = assessment_grouped.index.map(lambda i: i.right)
fig = go.Figure()
fig.add_bar(
x=assessment_grouped.index,
y=assessment_grouped.Bareme,
text=assessment_grouped.Eleve,
textposition="auto",
hovertemplate="",
marker_color="#4E89DE",
)
return [fig]
@app.callback( @app.callback(
[dash.dependencies.Output("lastsave", "children")], [dash.dependencies.Output("lastsave", "children")],
[dash.dependencies.Input("scores_table", "data"), dash.dependencies.State("csv", "value")], [
) dash.dependencies.Input("scores_table", "data"),
dash.dependencies.State("csv", "value"),
],
)
def save_scores(data, csv): def save_scores(data, csv):
scores = pd.DataFrame.from_records(data) scores = pd.DataFrame.from_records(data)
print(f"save at {csv} ({datetime.today()})") print(f"save at {csv} ({datetime.today()})")
@ -113,22 +221,26 @@ def highlight_value(df):
""" Cells style """ """ Cells style """
hight = [] hight = []
for v, color in COLORS.items(): for v, color in COLORS.items():
hight +=[ hight += [
{ {
'if': { "if": {"filter_query": "{{{}}} = {}".format(col, v), "column_id": col},
'filter_query': '{{{}}} = {}'.format(col, v), "backgroundColor": color,
'column_id': col "color": "white",
}, }
'backgroundColor': color, for col in df.columns
'color': 'white' if col not in NO_ST_COLUMNS.values()
} for col in df.columns if col not in NO_ST_COLUMNS.values()
] ]
return hight return hight
@app.callback( @app.callback(
[dash.dependencies.Output("scores_table", "columns"), dash.dependencies.Output("scores_table", "data"), dash.dependencies.Output("scores_table", "style_data_conditional"), ], [
dash.dependencies.Output("scores_table", "columns"),
dash.dependencies.Output("scores_table", "data"),
dash.dependencies.Output("scores_table", "style_data_conditional"),
],
[dash.dependencies.Input("csv", "value")], [dash.dependencies.Input("csv", "value")],
) )
def update_scores_table(value): def update_scores_table(value):
if not value: if not value:
raise PreventUpdate raise PreventUpdate
@ -137,4 +249,8 @@ def update_scores_table(value):
# stack = stack.drop(columns=["Nom", "Trimestre", "Date", "Competence", "Domaine", "Est_nivele", "Bareme"]) # stack = stack.drop(columns=["Nom", "Trimestre", "Date", "Competence", "Domaine", "Est_nivele", "Bareme"])
# except KeyError: # except KeyError:
# stack = stack # stack = stack
return [{"id": c, "name": c} for c in stack.columns], stack.to_dict('records'), highlight_value(stack) return (
[{"id": c, "name": c} for c in stack.columns],
stack.to_dict("records"),
highlight_value(stack),
)