Commit 47f27445 authored by Florent Chehab's avatar Florent Chehab

begin switch to react

parent 3fc9de99
......@@ -5,4 +5,6 @@ data
__pycache__
*.php
UVS_evals
\ No newline at end of file
UVS_evals
build
node_modules
\ No newline at end of file
image: python:3.6.5-jessie
# image: python:3.6.5-jessie
render:
stage: build
script:
- rm -rf ./data
- git clone --depth=1 $DATA_REPO_URL data && rm -rf ./data/.git
- pip install -r ./requierements.txt --quiet --quiet
- jupyter nbconvert --execute --to html_toc analysis.ipynb
artifacts:
paths:
- analysis.html
expire_in: 1 week
tags:
- docker
# render:
# stage: build
# script:
# - rm -rf ./data
# - git clone --depth=1 $DATA_REPO_URL data && rm -rf ./data/.git
# - pip install -r ./requierements.txt --quiet --quiet
# - jupyter nbconvert --execute --to html_toc analysis.ipynb
# artifacts:
# paths:
# - analysis.html
# expire_in: 1 week
# tags:
# - docker
deploy-stage:
image: floawfloaw/sshpass_bash
stage: deploy
script:
- bash deploy.sh
only:
- master
tags:
- docker
\ No newline at end of file
# deploy-stage:
# image: floawfloaw/sshpass_bash
# stage: deploy
# script:
# - bash deploy.sh
# only:
# - master
# tags:
# - docker
\ No newline at end of file
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-danger\" >\n",
" <strong style=\"font-size:20px;\">\n",
" Ce document repose en très grande partie sur du <code>JavaScript</code>. Il est fortement recommandé de le consulter depuis un ordinateur avec Firefox ou Chrome à jour.\n",
" </strong>\n",
" <br>\n",
" <br>\n",
" Une connexion internet est également requise afin de charger des libraires graphiques extérieures.\n",
" <br>\n",
" <i>Si vous voyez des lignes de codes et aucun graphique, c'est qu'au moins l'une de ces deux conditions n'est pas remplie.</i>\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-info\" >\n",
"<i>Tous commentaires ou suggestions sont les bienvenus. Merci de passer par le projet disponible sur le <a href=\"https://gitlab.utc.fr/chehabfl/Observatoire-Des-UVs\">GitLab</a> et le système de ticket associé. Le code source est libre ; les données ne sont pas publiquement accessibles.</i> \n",
"<br>\n",
"Les informations contenues dans ce document sont à traiter avec autant de rigueur que des informations internes à l'UTC (accessibles derrière le CAS sur l'ENT).\n",
"</div>"
]
},
{
"cell_type": "raw",
"metadata": {},
"source": [
"<script>\n",
" // Add a toggle button for showing (or not showing) source code.\n",
" function code_toggle() {\n",
" if (code_shown) {\n",
" $('div.input').hide('200');\n",
" $('.output_prompt').css({ visibility: 'hidden' });\n",
" $('#toggleButton').val('Afficher le code source')\n",
" } else {\n",
" $('div.input').show('200');\n",
" $('.output_prompt').removeAttr('style');\n",
" $('#toggleButton').val('Cacher le code source')\n",
" }\n",
" code_shown = !code_shown\n",
" }\n",
"\n",
" $(document).ready(function () {\n",
" code_shown = false;\n",
" $('div.input').hide();\n",
" $('.output_prompt').css({ visibility: 'hidden' });\n",
" $('table').addClass(\"table table-hover table-bordered table-striped\");\n",
" });\n",
"</script>\n",
"<form action=\"javascript:code_toggle()\">\n",
" <input type=\"submit\" id=\"toggleButton\" value=\"Afficher le code source\" class=\"btn btn-info\">\n",
"</form>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<center>\n",
"<img src=\"https://gitlab.utc.fr/LaTeX-UTC/Graphismes-UTC/raw/56dd9762de926727aa45c8279dcdf54a753335c8/logos/UTC/logo_UTC.png\" alt=\"Logo UTC\" width=\"200px\"/> \n",
"<br>\n",
"<font size=\"15\" style=\"line-height:1;\">Observatoire des évaluations d'UVs</font>\n",
"</center>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# For auto completion inside jupyter notebook\n",
"%config IPCompleter.greedy=True\n",
"\n",
"\n",
"import yaml # for the config file\n",
"import warnings # to issue warnings when needed\n",
"import os.path # for easy work with file paths\n",
"import copy # for deep copying some dicts\n",
"\n",
"\n",
"# utils functions\n",
"from src.generate_data import generate_data_file\n",
"from src.tools import is_connected, to_mardown_table_str\n",
"\n",
"\n",
"# For managing data\n",
"import json\n",
"from collections import OrderedDict\n",
"from datetime import datetime\n",
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"\n",
"# For plotting data\n",
"from IPython.core.display import HTML, display, Markdown\n",
"from plotly.offline import init_notebook_mode, plot, iplot\n",
"import plotly.graph_objs as go\n",
"\n",
"\n",
"# Some magic for file size optimization\n",
"if is_connected(debug=True):\n",
" # do not include plotly js directly\n",
" init_notebook_mode(connected=True) \n",
"else:\n",
" # include plotly js directly\n",
" import cufflinks as cf\n",
" cf.set_config_file(offline=True, world_readable=True, theme='ggplot')\n",
"\n",
"# First we take care of the configuration file\n",
"CONFIGURATION = yaml.load(open('./config.yml'))\n",
"ALL_SEMESTERS = {info['sem']:info['end_date'] for info in CONFIGURATION[\"other_semesters\"]}\n",
"ALL_SEMESTERS[CONFIGURATION[\"main_semester\"]['sem']] = CONFIGURATION[\"main_semester\"]['end_date']\n",
"MAIN_SEMESTER = CONFIGURATION[\"main_semester\"]['sem']\n",
"OTHER_SEMESTERS = [d['sem'] for d in CONFIGURATION[\"other_semesters\"]]\n",
"ALL_SEMESTERS_SORTED = sorted(list(ALL_SEMESTERS.keys()), key=lambda sem:sem[1:5]+str((ord(sem[0]) + 20)%26 ))\n",
"\n",
" \n",
"for semester in ALL_SEMESTERS.keys():\n",
" if not os.path.isfile('./data/' + semester + '.json'):\n",
" warnings.warn(\"\"\"\n",
" Il manque des fichiers de données des évaluations d'UVs pour le semestre {}\"\n",
" \"\"\".format(semester))\n",
" if CONFIGURATION['allow_generate']:\n",
" warnings.warn(\"Génération aléatoires des données manquantes.\")\n",
" generate_data_file(semester)\n",
" else:\n",
" raise ValueError(\"Données manquantes. Le fichier de configuration ne permet pas de générer des données.\")\n",
" ALL_SEMESTERS[semester] = datetime.strptime(ALL_SEMESTERS[semester], '%d/%m/%Y') \n",
" \n",
"restrict_uvs_to_dept = None\n",
"if CONFIGURATION['restrict_to_dept']:\n",
" restrict_uvs_to_dept = json.load(open('./uvs_dept/uvs_{}.json'.format(CONFIGURATION['restrict_to_dept'])))\n",
"\n",
"class SemesterData(object):\n",
" def __init__(self, d):\n",
" if restrict_uvs_to_dept is not None:\n",
" tmp = dict()\n",
" for key in d[\"data\"].keys():\n",
" if key in restrict_uvs_to_dept:\n",
" tmp[key] = d[\"data\"][key]\n",
" d[\"data\"] = tmp\n",
" \n",
" self.extraction_date = datetime.strptime(d['date'], '%d/%m/%Y') \n",
" self.DATA_RAW = OrderedDict(d['data'])\n",
" data = copy.deepcopy(self.DATA_RAW)\n",
" \n",
" def clean_date(date):\n",
" if date is not None and type(date) != 'datetime.datetime':\n",
" date = datetime.strptime(date, '%d/%m/%Y')\n",
" return date\n",
" \n",
" # cleaning dates\n",
" for uv, description in data.items():\n",
" for key in ['date_review_teacher', 'date_review_conseil']:\n",
" description[key] = clean_date(description[key])\n",
" \n",
" self.DATA = pd.DataFrame.from_dict(data, orient='index')\n",
" \n",
" d = self.DATA\n",
" self.nb_uvs = len(d.index)\n",
" taux_eval = d['nb_evals']/(d['nb_etu_registered']-d['nb_etu_abs'])\n",
" taux_eval[taux_eval>1]=1\n",
" taux_eval = taux_eval.fillna(1) # Sometimes there 0 students in a course but there are evaluations\n",
" self.taux_eval_arr = 100 * taux_eval.round(4)\n",
" self.taux_eval = sum(self.taux_eval_arr) / self.nb_uvs\n",
" self.uvs_with_evals = d.loc[pd.notna(d['date_review_teacher'])]\n",
" self.nb_uvs_with_evals = len(self.uvs_with_evals.index)\n",
" self.uvs_with_com = d.loc[ d['teacher_comment'] > '']\n",
" self.nb_uvs_with_com = len(self.uvs_with_com)\n",
" self.taux_seen = 100 * self.nb_uvs_with_evals / self.nb_uvs\n",
" self.taux_comment = 100 * self.nb_uvs_with_com / self.nb_uvs\n",
" self.number_of_inscription = sum(d['nb_etu_registered'])\n",
" \n",
" \n",
"# import\n",
"EVALS = {}\n",
"\n",
"for semester in ALL_SEMESTERS.keys():\n",
" data_json = json.load(open('./data/' + semester + '.json'))\n",
" if data_json['semester'] != semester:\n",
" print(data_json[\"semester\"], semester)\n",
" raise ValueError(\"Inconsistent data file naming !\")\n",
" \n",
" EVALS[semester] = SemesterData(data_json)\n",
" \n",
"EVALS_MAIN_SEM = EVALS[MAIN_SEMESTER]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"str_tmp = \"\"\"\n",
"</br>\n",
"<center>\n",
" <span style='font-size:40px'>\n",
" Semestre d'étude : {0}\n",
" </span>\n",
" <br><br>\n",
" <span style='font-size:30px'>\n",
" Autre(s) semestre(s) pour comparaison : {1}\n",
" </span>\n",
"</center><br>\n",
"\"\"\".format(MAIN_SEMESTER, \", \".join(x for x in OTHER_SEMESTERS))\n",
"HTML(str_tmp)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Introduction\n",
"\n",
"## Présentation des données\n",
"\n",
"### Âge des données"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"str_tmp = \"Les données pour chaque semestre ont été extraites aux dates suivantes : \\n\\n \"\n",
"t = [[\"Semestre\", \"Date d'extraction\"]]\n",
"for sem in EVALS.keys():\n",
" t.append([sem, EVALS[sem].extraction_date.strftime('%d/%m/%Y')]) \n",
"Markdown(str_tmp + to_mardown_table_str(t))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Structure des données\n",
"\n",
"Pour chaque semestre, nous avons les informations des évaluations telles que visibles par les étudiants sur l'ENT aux dates d'extraction précisées ci-dessus.\n",
"\n",
"<br>\n",
"Nous connaissons pour sûr :\n",
"- Le code de l'UV ;\n",
"- L'intitulé de l'UV ;\n",
"- Le nombre d'étudiants inscrits ;\n",
"- Le nombre d'étudiants marqués comme _absents_ ;\n",
"- Le nombre d'étudiants qui ont obtenu l'UV ;\n",
"- Le nombre d'évaluations saisies par les étudiants ;\n",
"- Les statistiques pour chacune des questions (i.e. le nombre de `++`, etc. pour chaque question) ;\n",
"- Le nom du ou de la responsable de l'UV ;\n",
"\n",
"<br>\n",
"Sont éventuellement présents :\n",
"- La date à laquelle le responsable de l'UV a pris connaissance des évaluations ;\n",
"- Le rapport saisie par le ou la responsable de l'UV ;\n",
"- La date à laquelle le conseil de perfectionnement a émis un avis ;\n",
"- L'avis du conseil de perfectionnement.\n",
"\n",
"Voici un exemple pour l'UV MT23 :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(EVALS_MAIN_SEM.DATA.loc[\"NF16\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Remarque\n",
"\n",
"Lorsque les statistiques des évaluations d'UVs (le nombre de `++`, de `+`, etc.) seront analysées de manière quantitative la table de conversion _symétrique_ suivante est employée :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"POSSIBLE_ANSWERS = [\"--\",\"-\",\"+\",\"++\"]\n",
"POSSIBLE_ANSWERS_COEFFS = [-3,-1,1,3]\n",
"\n",
"t = [[\"Sigle\", \"Valeur associée\"]]\n",
"for ans, coeff in zip(POSSIBLE_ANSWERS, POSSIBLE_ANSWERS_COEFFS):\n",
" t.append([\"`{}`\".format(ans), str(coeff)]) \n",
"Markdown(to_mardown_table_str(t))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# some functions and constants\n",
"\n",
"def get_nb_evals(stats):\n",
" return sum([stats['1'][s] for s in POSSIBLE_ANSWERS])\n",
"\n",
"def get_mark_q(stat, q): \n",
" if type(q) is int:\n",
" q = str(q)\n",
" \n",
" val = sum([stat[q][POSSIBLE_ANSWERS[i]] * \\\n",
" POSSIBLE_ANSWERS_COEFFS[i] \\\n",
" for i in range(len(POSSIBLE_ANSWERS_COEFFS))])\\\n",
" / get_nb_evals(stat)\n",
" return round(val,2)\n",
" \n",
"POSSIBLE_ANSWERS_COL = [\n",
" 'rgb(255,48,48)',\n",
" 'rgb(255,165,0)', \n",
" 'rgb(144,238,144)', \n",
" 'rgb(48,221,48)'\n",
"]\n",
"\n",
"ORANGE = 'rgb(255,126,24)' # Plotly orange\n",
"\n",
"# Lets have some standard scales\n",
"SCALE_PERCENTAGE = [-1,101]\n",
"SCALE_MARK = [-3.1, 3.1]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Informations générales\n",
"\n",
"_NB : Lorsque'une analyse comparative est réalisée, elle est faite par rapport aux données des précédents semestres._\n",
"\n",
"<br>\n",
"\n",
"### Taux de réponse"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"t = [[\"Semestre\",\n",
" \"Nombre d'UVs\", \n",
" \"Nombres d'inscriptions (d'étudiants aux UVs)\",\n",
" \"Participation moyenne des étudiants aux évaluations\" , \n",
" \"UVs pour laquelle le ou la responsable a indiqué avoir visualisé les évaluations\", \n",
" \"UVs pour laquelle le ou la responsable a saisi un rapport\"]]\n",
"\n",
"for sem in ALL_SEMESTERS_SORTED:\n",
" d = EVALS[sem]\n",
" t.append([sem, str(d.nb_uvs), str(d.number_of_inscription),\n",
" \"{0:.1f}%\".format(d.taux_eval), \n",
" str(d.nb_uvs_with_evals)+\" ({0:.1f}%)\".format(d.taux_seen), \n",
" str(d.nb_uvs_with_com)+\" ({0:.1f}%)\".format(d.taux_comment)])\n",
" \n",
"Markdown(to_mardown_table_str(t))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"traces = []\n",
"\n",
"for sem in ALL_SEMESTERS_SORTED:\n",
" d = EVALS[sem]\n",
" traces += [go.Bar(\n",
" x=[\"Participation moyenne des étudiants\", \n",
" \"UVs où le/la resps a <i>vu</i> les éval.\", \n",
" \"UVs où le/la resp. a posté un commentaire\"\n",
" ],\n",
" y=[\n",
" d.taux_eval,\n",
" d.taux_seen,\n",
" d.taux_comment\n",
" ],\n",
" name=sem\n",
" )]\n",
"\n",
"layout = go.Layout(\n",
" barmode='group',\n",
" title = \"Analyse temporelle de l'engagement dans les évaluations d'UVs\",\n",
" yaxis=dict(\n",
" range=SCALE_PERCENTAGE,\n",
" title='Taux',\n",
" ),\n",
")\n",
"\n",
"iplot(go.Figure(data=traces, layout=layout),show_link=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"traces = []\n",
"\n",
"for sem in ALL_SEMESTERS_SORTED:\n",
" d = EVALS[sem]\n",
" taux_eval = d.taux_eval_arr\n",
" traces += [go.Box(\n",
" y=taux_eval,\n",
" text=taux_eval.index,\n",
" name=sem\n",
"\n",
" )]\n",
"\n",
"layout = go.Layout(\n",
" title = \"Participation des étudiants au cours des semestres\",\n",
" yaxis=dict(\n",
" range=SCALE_PERCENTAGE,\n",
" title='Taux',\n",
" ),\n",
")\n",
"\n",
"iplot(go.Figure(data=traces, layout=layout), show_link=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Délai de réponse des responsables d'UVs\n",
"\n",
"#### Pour le semestre d'étude principal"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"X = EVALS_MAIN_SEM.uvs_with_evals['date_review_teacher'].sort_values()\n",
"Y = [round(100*float(i+1)/EVALS_MAIN_SEM.nb_uvs,2) for i in range(len(X.index))]\n",
"graph_data = [\n",
" go.Scatter(\n",
" x=X,\n",
" y=Y,\n",
" text=X.index,\n",
" marker=dict(color=ORANGE)\n",
" )\n",
"]\n",
"layout = go.Layout(\n",
" title = \"Délai de <i>réponse</i> des responsables d'UVs lors du semestre \"+MAIN_SEMESTER,\n",
" yaxis=dict(\n",
" range=SCALE_PERCENTAGE,\n",
" title='Taux de réponse',\n",
" ),\n",
" xaxis=dict(\n",
" title=\"Date\"\n",
" )\n",
")\n",
"\n",
"iplot(go.Figure(data=graph_data, layout=layout), show_link=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### En comparaison avec les précédents semestres\n",
"\n",
"Pour cette comparaison, les dates sont renormalisées par rapport à la date correspondant au dernier jour des finaux du semestre en question. Les dates de fins des finaux sont les suivantes :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"t = [[\"Semestre\", \"Date de la fin des finaux\"]]\n",
"for sem in ALL_SEMESTERS_SORTED:\n",
" t.append([sem, ALL_SEMESTERS[sem].strftime('%d/%m/%Y')]) \n",
"Markdown(to_mardown_table_str(t))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"traces = []\n",
"for sem in ALL_SEMESTERS_SORTED:\n",
" sem_end_date = ALL_SEMESTERS[sem].toordinal()\n",
" d = EVALS[sem]\n",
" X = d.uvs_with_evals['date_review_teacher'].sort_values().apply(datetime.toordinal)\n",
" Y = [round(100*float(i+1)/d.nb_uvs,2) for i in range(len(X.index))]\n",
" traces.append(\n",
" go.Scatter(\n",
" x=X-sem_end_date ,\n",
" y=Y,\n",
" text=d.uvs_with_evals.sort_values(by=['date_review_teacher']).index,\n",
" name=sem\n",
" ) \n",
" )\n",
" \n",
"\n",
"layout = go.Layout(\n",
" title = \"Délai de <i>réponse</i> des responsables d'UVs\",\n",
" yaxis=dict(\n",
" range=SCALE_PERCENTAGE,\n",
" title=\"Taux des UVs qui dont les évals. ont été <i>vues</i> par les resp\",\n",
" ),\n",
" xaxis=dict(\n",
" title=\"Nombre de jours après la fin des finaux\"\n",
" )\n",
")\n",
"\n",
"iplot(go.Figure(data=traces, layout=layout), show_link=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Analyse quantitative"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ASKED_QUESTIONS = \"\"\"\n",
"Pour rappel voici les questions posées :\n",
"\n",
"1. Clarté des objectifs et du programme de l'UV\n",
"2. Y a-t-il adéquation entre le programme annoncé et le programme réalisé ?\n",
"3. Maîtrise des antécédents et pré-requis nécessaires\n",
"4. Qualité pédagogique de l'équipe enseignante\n",
"5. Articulation et cohérence des activités\n",
"6. Qualité des supports pédagogiques\n",
"7. Adéquation des moyens matériels\n",
"8. Adéquation des contrôles et des évaluations\n",
"9. Quantité de travail demandée\n",
"10. Appréciation globale de l'UV\n",
"\"\"\"\n",
"\n",
"Markdown(ASKED_QUESTIONS)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vue d'ensemble des questions\n",
"\n",
"### Vue synthétique"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_stat_by_question(question, s):\n",
" q = str(question)\n",
" res = 0\n",
" for i, row in EVALS_MAIN_SEM.DATA.iterrows():\n",
" res += row[\"stats\"][q][s] / get_nb_evals(row[\"stats\"])\n",
" return res / EVALS_MAIN_SEM.nb_uvs * 100\n",
"\n",
"traces = []\n",
"for ans, col in zip(POSSIBLE_ANSWERS, POSSIBLE_ANSWERS_COL):\n",
" traces.append(\n",
" go.Bar(\n",
" x=[\"Question \"+str(i) for i in range(1,11)],\n",
" y=[get_stat_by_question(i, ans) for i in range(1,11)],\n",
" name=ans,\n",
" marker=dict(color=col)\n",
" )\n",
" )\n",
"\n",
"layout = go.Layout(\n",
" barmode='stack',\n",
" title=\"Pourcentage moyen de chaque type d'avis pour chaque question en \"+MAIN_SEMESTER,\n",
" yaxis=dict(\n",
" range=SCALE_PERCENTAGE,\n",
" title=\"Pourcentage\",\n",
" ),\n",
")\n",
"\n",
"iplot(go.Figure(data=traces, layout=layout), show_link=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Vue détaillée\n",
"\n",
"_Ici les évaluations (`++`, ...) sont converties en note numérique._"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"traces = []\n",
"data = EVALS_MAIN_SEM.DATA\n",
"for q in [str(i) for i in range(1,11)]:\n",
" traces.append(\n",
" go.Box(\n",
" y=[get_mark_q(row[\"stats\"], q) for ind, row in data.iterrows()],\n",
" text=data.index,\n",
" name=\"Question \"+q,\n",
" )\n",
" )\n",
"\n",
"\n",
"layout = go.Layout(\n",
" title = \"Répartition des notes obetnues pour chaque question en \" + MAIN_SEMESTER,\n",
" yaxis=dict(\n",
" range=SCALE_MARK,\n",
" title='Notes obtenues',\n",
" ),\n",
")\n",
"\n",
"iplot(go.Figure(data=traces, layout=layout), show_link=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Analyse de la question 10 (Appréciation globale de l'UV)\n",
"\n",
"### Analyse pour le semestre d'étude"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Markdown(\"_Pour rappel, le semestre d'étude principal est : {}._\".format(MAIN_SEMESTER))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-success\">\n",
" <strong>\n",
" Pour les graphiques ci-dessous,\n",
" en cliquant sur les points, la visualisation en détail d'une UV \n",
" (disponible en bas de page) se mettra automatiquement à jour\n",
" avec les données correspondantes.\n",
" </strong>\n",
"</div>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_stat_per_q(row, q, stat):\n",
" return row['stats'][q][stat]\n",
" \n",
"def get_nb_mm_q10(row):\n",
" return get_stat_per_q(row, '10', '--')\n",
"\n",
"def get_nb_m_q10(row):\n",
" return get_stat_per_q(row, '10', '-')\n",
"\n",
"def get_nb_m_or_mm_q10(row):\n",
" return get_nb_mm_q10(row) + get_nb_m_q10(row)\n",
"\n",
"traces = []\n",
"data = EVALS_MAIN_SEM.DATA\n",
"tmp1 = data.apply(get_nb_mm_q10, axis=1) / data['nb_evals']\n",
"traces.append(\n",
" go.Scatter(\n",
" x=tmp1.sort_values().index,\n",
" y=tmp1.sort_values()*100,\n",
" name='<b>--</b>'\n",
" ) \n",
")\n",
" \n",
"tmp2 = data.apply(get_nb_m_or_mm_q10, axis=1) / data[\"nb_evals\"]\n",
"traces.append(\n",
" go.Scatter(\n",
" x=tmp2[tmp1.sort_values().index].index,\n",
" y=tmp2[tmp1.sort_values().index]*100,\n",
" name=\"<b>-</b> ou <b>--</b>\"\n",
" ) \n",
")\n",
"\n",
"layout = go.Layout(\n",
" title = \"\"\"Visualisation du pourcentage d'avis négatifs\n",
"<b>--</b> et (<b>-</b> ou <b>--</b>) <br> \n",
"concernant l'appréciation globale de l'UV en {}\"\"\".format(MAIN_SEMESTER),\n",
" yaxis=dict(\n",
" range=SCALE_PERCENTAGE,\n",
" title=\"Pourcentage\",\n",