Compare commits

...

3 Commits

5 changed files with 109 additions and 40 deletions

View File

@ -1,5 +1,5 @@
Trimestre,Nom,Date,Exercice,Question,Competence,Domaine,Commentaire,Bareme,Est_nivele,Star Tice,Umberto Dingate,Starlin Crangle,Humbert Bourcq,Gabriella Handyside,Stewart Eaves,Erick Going,Ase Praton,Rollins Planks,Dunstan Sarjant,Stacy Guiton,Ange Stanes,Amabelle Elleton,Darn Broomhall,Dyan Chatto,Keane Rennebach,Nari Paulton,Brandy Wase,Jaclyn Firidolfi,Violette Lockney
1,DS,12/01/2021,Exercice 1,1,Calculer,Plop,Coucou,1,1,,,1.0,0,1.0,2.0,3.0,0.0,3.0,3.0,2.0,,1.0,,,,,,,
1,DS,12/01/2021,Exercice 1,2,Calculer,C'est trop chouette!,Coucou,1,1,,,1.0,2,,,3.0,3.0,,,,,2.0,,,,,,,
1,DS,12/01/2021,Exercice 1,3,Calculer,Null,Coucou,1,1,,,,3,2.0,,,,,,,,3.0,,,,,,,
1,DS,12/01/2021,Exercice 1,3,Calculer,Nié,DChic,1,1,,,,2,,,,,,,,,,,,,,,,
1,DS,12/01/2021,Exercice 1,1,Calculer,Plop,Coucou,1,1,,,1,0,1,2,3,0,3,3,2,,1,,,,,,,
1,DS,12/01/2021,Exercice 1,2,Calculer,C'est trop chouette!,Coucou,1,1,,,1,2,,,3,3,,,,,2,,,,,,,
1,DS,12/01/2021,Exercice 1,3,Calculer,Null,Coucou,1,1,,,,3,2,,,,,,,,3,,,,,,,
1,DS,12/01/2021,Exercice 1,3,Calculer,Nié,DChic,1,1,,,,2,.,,,,,,,,,,,,,,,

1 Trimestre Nom Date Exercice Question Competence Domaine Commentaire Bareme Est_nivele Star Tice Umberto Dingate Starlin Crangle Humbert Bourcq Gabriella Handyside Stewart Eaves Erick Going Ase Praton Rollins Planks Dunstan Sarjant Stacy Guiton Ange Stanes Amabelle Elleton Darn Broomhall Dyan Chatto Keane Rennebach Nari Paulton Brandy Wase Jaclyn Firidolfi Violette Lockney
2 1 DS 12/01/2021 Exercice 1 1 Calculer Plop Coucou 1 1 1.0 1 0 1.0 1 2.0 2 3.0 3 0.0 0 3.0 3 3.0 3 2.0 2 1.0 1
3 1 DS 12/01/2021 Exercice 1 2 Calculer C'est trop chouette! Coucou 1 1 1.0 1 2 3.0 3 3.0 3 2.0 2
4 1 DS 12/01/2021 Exercice 1 3 Calculer Null Coucou 1 1 3 2.0 2 3.0 3
5 1 DS 12/01/2021 Exercice 1 3 Calculer Nié DChic 1 1 2 .

View File

@ -68,6 +68,7 @@ layout = html.Div(
children=[
dcc.Graph(
id="fig_exam_histo",
config={"displayModeBar": False},
)
],
id="fig_exam_histo_container",
@ -76,6 +77,7 @@ layout = html.Div(
children=[
dcc.Graph(
id="fig_questions_bar",
config={"displayModeBar": False},
)
],
id="fig_questions_bar_container",

View File

@ -205,5 +205,12 @@ def update_questions_bar(finale_scores):
fig.update_layout(
height=500,
margin=dict(l=5, r=5, b=5, t=5),
)
legend=dict(
orientation="h",
yanchor="bottom",
y=1.02,
xanchor="right",
x=1
)
)
return [fig]

View File

@ -72,22 +72,31 @@ def get_score_colors():
def get_level_color_bar():
return [
{"score": s["value"], "name": s["comment"], "color": s["color"]}
{"score": str(s["value"]), "name": s["comment"], "color": s["color"]}
for s in SCORES_CONFIG.values()
]
is_none_score = lambda x: on_column.is_none_score(x, SCORES_CONFIG)
format_score = lambda x: on_column.format_score(x, SCORES_CONFIG)
score_to_numeric_score = lambda x: on_column.score_to_numeric_score(x, SCORES_CONFIG)
score_to_mark = lambda x: on_column.score_to_mark(
x, max([v["value"] for v in SCORES_CONFIG.values() if isinstance(v["value"], int)])
)
def filter_clean_score(scores):
filtered_scores = scores[~scores.apply(is_none_score, axis=1)]
filtered_scores = filtered_scores.assign(
score=filtered_scores.apply(format_score, axis=1)
)
return filtered_scores
def score_to_final_mark(scores):
""" Compute marks then reduce to final mark per student """
filtered_scores = scores[~scores.apply(is_none_score, axis=1)]
filtered_scores = filter_clean_score(scores)
filtered_scores = filtered_scores.assign(
score=filtered_scores.apply(score_to_numeric_score, axis=1)
)
@ -106,9 +115,10 @@ def pivot_score_on(scores, index, columns, aggfunc="size"):
It assumes thant scores are levels
"""
filtered_scores = scores[~scores.apply(is_none_score, axis=1)]
filtered_scores = filter_clean_score(scores)
filtered_scores["score"] = filtered_scores["score"].astype(str)
pt = pd.pivot_table(
scores,
filtered_scores,
index=index,
columns=columns,
aggfunc=aggfunc,

View File

@ -43,6 +43,57 @@ def is_none_score(x, score_config):
return x["score"] in none_values or pd.isnull(x["score"])
def format_score(x, score_config):
"""Make sure that score have the appropriate format
>>> import pandas as pd
>>> d = {"Eleve":["E1"]*6,
... "score_rate": [1]*6,
... "is_leveled":[0]+[1]*5,
... "score":[0.33, ".", "a", 1, 2, 3],
... }
>>> score_config = {
... 'BAD': {'value': 0, 'numeric_value': 0},
... 'FEW': {'value': 1, 'numeric_value': 1},
... 'NEARLY': {'value': 2, 'numeric_value': 2},
... 'GOOD': {'value': 3, 'numeric_value': 3},
... 'NOTFILLED': {'value': '', 'numeric_value': 'None'},
... 'NOANSWER': {'value': '.', 'numeric_value': 0},
... 'ABS': {'value': 'a', 'numeric_value': 'None'}
... }
>>> df = pd.DataFrame(d)
>>> df.apply(lambda x:format_score(x, score_config), axis=1)
0 0.33
1 .
2 a
3 1
4 2
5 3
dtype: object
>>> format_score({"score": "1.0", "is_leveled": 1}, score_config)
1
>>> format_score({"score": "3.0", "is_leveled": 1}, score_config)
3
>>> format_score({"score": 4, "is_leveled": 1}, score_config)
Traceback (most recent call last):
...
ValueError: 4 (<class 'int'>) can't be a score
"""
if not x["is_leveled"]:
return float(x["score"])
try:
score = int(float(x["score"]))
except ValueError:
score = str(x["score"])
if score in [v["value"] for v in score_config.values()]:
return score
raise ValueError(f"{x['score']} ({type(x['score'])}) can't be a score")
def score_to_numeric_score(x, score_config):
"""Convert a score to the corresponding numeric value
@ -81,7 +132,7 @@ def score_to_numeric_score(x, score_config):
def score_to_mark(x, score_max, rounding=lambda x: round(x, 2)):
"""Compute the mark from the score
"""Compute the mark from "score" which have to be filtered and in numeric form
if the item is leveled then the score is multiply by the score_rate
otherwise it copies the score
@ -92,39 +143,38 @@ def score_to_mark(x, score_max, rounding=lambda x: round(x, 2)):
:return: the mark
>>> import pandas as pd
>>> d = {"Eleve":["E1"]*6 + ["E2"]*6,
... "score_rate":[1]*2+[2]*2+[2]*2 + [1]*2+[2]*2+[2]*2,
... "is_leveled":[0]*4+[1]*2 + [0]*4+[1]*2,
... "score":[1, 0.33, 2, 1.5, 1, 3, 0.666, 1, 1.5, 1.2, 2, 3],
>>> d = {"Eleve":["E1"]*7,
... "score_rate": [1]*7,
... "is_leveled":[0]+[1]*6,
... "score":[0.33, "", ".", "a", 1, 2, 3],
... }
>>> score_config = {
... 'BAD': {'value': 0, 'numeric_value': 0},
... 'FEW': {'value': 1, 'numeric_value': 1},
... 'NEARLY': {'value': 2, 'numeric_value': 2},
... 'GOOD': {'value': 3, 'numeric_value': 3},
... 'NOTFILLED': {'value': '', 'numeric_value': 'None'},
... 'NOANSWER': {'value': '.', 'numeric_value': 0},
... 'ABS': {'value': 'a', 'numeric_value': 'None'}
... }
>>> df = pd.DataFrame(d)
>>> df.loc[0]
Eleve E1
score_rate 1
is_leveled 0
score 1.0
Name: 0, dtype: object
>>> score_to_mark(df.loc[0], 3)
1.0
>>> df.loc[10]
Eleve E2
score_rate 2
is_leveled 1
score 2.0
Name: 10, dtype: object
>>> score_to_mark(df.loc[10], 3)
1.33
>>> df = df[~df.apply(lambda x:is_none_score(x, score_config), axis=1)]
>>> df["score"] = df.apply(lambda x:score_to_numeric_score(x, score_config), axis=1)
>>> df.apply(lambda x:score_to_mark(x, 3), axis=1)
0 0.33
2 0.00
4 0.33
5 0.67
6 1.00
dtype: float64
>>> from .on_value import round_half_point
>>> score_to_mark(df.loc[10], 3, round_half_point)
1.5
>>> df.loc[1]
Eleve E1
score_rate 1
is_leveled 0
score 0.33
Name: 1, dtype: object
>>> score_to_mark(df.loc[1], 3)
0.33
>>> df.apply(lambda x:score_to_mark(x, 3, round_half_point), axis=1)
0 0.5
2 0.0
4 0.5
5 0.5
6 1.0
dtype: float64
"""
if x["is_leveled"]:
if x["score"] not in list(range(score_max + 1)):