Feat: Hist graph and describe
This commit is contained in:
parent
cfd5928853
commit
f6bfac4144
@ -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),
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user