129 lines
3.5 KiB
Python
129 lines
3.5 KiB
Python
#!/use/bin/env python
|
|
# encoding: utf-8
|
|
|
|
from recopytex.database.filesystem.loader import CSVLoader
|
|
from recopytex.datalib.dataframe import column_values_to_column
|
|
import recopytex.datalib.on_score_column as on_column
|
|
import pandas as pd
|
|
|
|
LOADER = CSVLoader("./test_confia.ml")
|
|
SCORES_CONFIG = LOADER.get_config()["scores"]
|
|
|
|
|
|
def unstack_scores(scores):
|
|
"""Put student_name values to columns
|
|
|
|
:param scores: Score dataframe with one line per score
|
|
:returns: Scrore dataframe with student_name in columns
|
|
|
|
"""
|
|
kept_columns = [col for col in LOADER.score_columns if col != "score"]
|
|
return column_values_to_column("student_name", "score", kept_columns, scores)
|
|
|
|
|
|
def stack_scores(scores):
|
|
"""Student columns are melt to rows with student_name column
|
|
|
|
:param scores: Score dataframe with student_name in columns
|
|
:returns: Scrore dataframe with one line per score
|
|
|
|
"""
|
|
kept_columns = [
|
|
c for c in LOADER.score_columns if c not in ["score", "student_name"]
|
|
]
|
|
student_names = [c for c in scores.columns if c not in kept_columns]
|
|
return pd.melt(
|
|
scores,
|
|
id_vars=kept_columns,
|
|
value_vars=student_names,
|
|
var_name="student_name",
|
|
value_name="score",
|
|
)
|
|
|
|
|
|
def get_tribes():
|
|
return LOADER.get_tribes()
|
|
|
|
|
|
def get_exams(tribe):
|
|
return LOADER.get_exams([tribe])
|
|
|
|
|
|
def get_record_scores(exam):
|
|
return LOADER.get_exam_scores(exam)
|
|
|
|
|
|
def get_unstack_scores(exam):
|
|
flat_scores = LOADER.get_exam_scores(exam)
|
|
return unstack_scores(flat_scores)
|
|
|
|
|
|
def get_students_from_exam(exam):
|
|
flat_scores = LOADER.get_exam_scores(exam)
|
|
return flat_scores["student_name"].unique()
|
|
|
|
|
|
def get_score_colors():
|
|
score_color = {}
|
|
for key, score in SCORES_CONFIG.items():
|
|
score_color[score["value"]] = score["color"]
|
|
return score_color
|
|
|
|
|
|
def get_level_color_bar():
|
|
return [
|
|
{"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 = filter_clean_score(scores)
|
|
filtered_scores = filtered_scores.assign(
|
|
score=filtered_scores.apply(score_to_numeric_score, axis=1)
|
|
)
|
|
filtered_scores = filtered_scores.assign(
|
|
mark=filtered_scores.apply(score_to_mark, axis=1)
|
|
)
|
|
final_score = filtered_scores.groupby(["student_name"])[
|
|
["mark", "score_rate"]
|
|
].sum()
|
|
return [final_score.reset_index().to_dict("records")]
|
|
|
|
|
|
def pivot_score_on(scores, index, columns, aggfunc="size"):
|
|
"""Pivot scores on index, columns with aggfunc
|
|
|
|
It assumes thant scores are levels
|
|
|
|
"""
|
|
filtered_scores = filter_clean_score(scores)
|
|
filtered_scores["score"] = filtered_scores["score"].astype(str)
|
|
pt = pd.pivot_table(
|
|
filtered_scores,
|
|
index=index,
|
|
columns=columns,
|
|
aggfunc=aggfunc,
|
|
fill_value=0,
|
|
)
|
|
return pt
|
|
|