Commit 018b2df2 authored by Florent Chehab's avatar Florent Chehab
Browse files

init

parents
*.html
.ipynb_checkpoints
proj_env
data
image: python:3.6.5-jessie
pages:
stage: deploy
script:
- pip install -r ./requierements.txt --quiet --quiet
- cd ./analysis
- jupyter nbconvert --execute --to html_toc analysis.ipynb
- cd ../
- mkdir .public
- mv ./analysis/analysis.html .public/index.html
- mv .public public
artifacts:
paths:
- public
expire_in: 1 year
only:
- master
tags:
- docker
# TODO
source activate proj_env/bin/activate
\ No newline at end of file
{
"cells": [
{
"cell_type": "raw",
"metadata": {},
"source": [
"<script>\n",
" function code_toggle() {\n",
" if (code_shown){\n",
" $('div.input').hide('200');\n",
" $('#toggleButton').val('Afficher le code source')\n",
" } else {\n",
" $('div.input').show('200');\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",
" });\n",
"</script>\n",
"<form action=\"javascript:code_toggle()\">\n",
" <input type=\"submit\" id=\"toggleButton\" value=\"Afficher le code source\" style=\"margin-left: auto;margin-right: auto; display:block;\" 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",
"<H1>Observatoire des évaluations d'UVs</H1>\n",
"</center>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import socket\n",
"\n",
"def is_connected():\n",
" hostname = \"www.utc.fr\"\n",
" try:\n",
" host = socket.gethostbyname(hostname)\n",
" s = socket.create_connection((host, 80), 2)\n",
" return True\n",
" except:\n",
" pass\n",
" return False"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# For auto completion inside jupyter notebook\n",
"%config IPCompleter.greedy=True\n",
"\n",
"import json\n",
"from collections import OrderedDict\n",
"from datetime import datetime\n",
"\n",
"from IPython.core.display import HTML\n",
"from IPython.core.display import Markdown\n",
"\n",
"# For plotting data\n",
"from plotly.offline import init_notebook_mode, plot, iplot\n",
"import plotly.graph_objs as go\n",
"\n",
"if is_connected():\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",
"# pandas and numpy for managing data\n",
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"\n",
"# import data\n",
"data_json = json.load(open('../data/A17.json'))\n",
"DATE = data_json[\"date\"]\n",
"semester = data_json[\"semester\"]\n",
"data_dict = OrderedDict(data_json[\"data\"])\n",
"\n",
"# first we convert the date and time\n",
"for uv, description in data_dict.items():\n",
" if description[\"date_review\"] is not None:\n",
" description[\"date_review\"] = datetime.strptime(description[\"date_review\"], '%d/%m/%Y') \n",
"\n",
"# and we make it pandas dataframe\n",
"data_pd = pd.DataFrame.from_dict(data_dict, orient = \"index\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Généralités\n",
"\n",
"### Présentation des données"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Markdown(\"Les données datent du : \" + str(DATE))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(list(data_pd))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Voici un exemple de ligne (il y a une ligne par UV) :\n",
"<div class=\"alert alert-success\">\n",
" <strong>Success!</strong> Indicates a successful or positive action.\n",
"</div>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(data_pd.iloc[0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Taux de réponse"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"nb_uvs = len(data_pd.index)\n",
"print(\"Nombre d'UVs étudiées : \"+str(nb_uvs))\n",
"\n",
"uvs_with_evals = data_pd.loc[pd.notna(data_pd[\"date_review\"])]\n",
"nb_uvs_with_evals = len(uvs_with_evals.index)\n",
"print(\"Nombre d'UVs où le responsable a visualisé les évaluations : \"+str(nb_uvs_with_evals))\n",
"print(\"Taux de visualisation : \"+\"{0:.0f}%\".format(float(nb_uvs_with_evals)/nb_uvs * 100))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Délai de réponse des responsables d'UVs"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"graph_data = [\n",
" go.Scatter(\n",
" x=uvs_with_evals.sort_values(by=['date_review'])['date_review'],\n",
" y=[100*float(i+1)/nb_uvs for i,e in enumerate(uvs_with_evals.index)],\n",
" text=uvs_with_evals.sort_values(by=['date_review']).index\n",
" )\n",
"]\n",
"layout = go.Layout(\n",
" title = \"Délai de réponse\",\n",
" yaxis=dict(\n",
" range=[0, 100],\n",
" title='Taux de réponse',\n",
" ),\n",
" xaxis=dict(\n",
" title=\"Date\"\n",
" )\n",
" \n",
")\n",
"\n",
"iplot(go.Figure(data=graph_data, layout=layout))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Analyse quantitative"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_stats_uv_question(stats, question):\n",
" q = str(question)\n",
" return stats[q][\"++\"], stats[q][\"+\"], stats[q][\"-\"], stats[q][\"--\"] \n",
"\n",
"\n",
"nb_pp, nb_p, nb_m, nb_mm = 0, 0, 0, 0\n",
"for i, row in data_pd.iterrows():\n",
" for q in range(1,11):\n",
" a, b, c, d = get_stats_uv_question(row[\"stats\"],q)\n",
" nb_pp += a\n",
" nb_p += b\n",
" nb_m += c\n",
" nb_mm += d\n",
"\n",
"print(nb_pp, nb_p, nb_m, nb_mm)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"color_mm = 'rgb(255,48,48)'\n",
"color_m = 'rgb(255,165,0)'\n",
"color_p = 'rgb(144,238,144)'\n",
"color_pp = 'rgb(48,221,48)'\n",
"\n",
"q_lists_pd = [str(i) for i in range(1,11)] # TODO BETTER"
]
},
{
"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 data_pd.iterrows():\n",
" res += row[\"stats\"][q][s]\n",
" return res \n",
"\n",
"\n",
"\n",
"q_list = [\"q\"+str(i) for i in range(1,11)]\n",
"\n",
"\n",
"\n",
"trace1 = go.Bar(\n",
" x=q_list,\n",
" y=[get_stat_by_question(i, \"--\") for i in range(1,11)],\n",
" name='--',\n",
" marker=dict(color=color_mm)\n",
")\n",
"trace2 = go.Bar(\n",
" x=q_list,\n",
" y=[get_stat_by_question(i, \"-\") for i in range(1,11)],\n",
" name='-',\n",
" marker=dict(color=color_m)\n",
")\n",
"trace3 = go.Bar(\n",
" x=q_list,\n",
" y=[get_stat_by_question(i, \"+\") for i in range(1,11)],\n",
" name='+',\n",
" marker=dict(color=color_p)\n",
")\n",
"trace4 = go.Bar(\n",
" x=q_list,\n",
" y=[get_stat_by_question(i, \"++\") for i in range(1,11)],\n",
" name='++',\n",
" marker=dict(color=color_pp)\n",
")\n",
"\n",
"data = [trace1, trace2, trace3, trace4]\n",
"layout = go.Layout(\n",
" barmode='stack',\n",
" title=\"Total cumulé de l'ensemble des évaluations d'UVs pour chaque question\"\n",
")\n",
"\n",
"\n",
"fig = go.Figure(data=data, layout=layout)\n",
"iplot(fig)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_mm_per_row(row, relative = True):\n",
" nb_mm = 0\n",
" # for q in q_lists_pd :\n",
" # nb_mm += row[\"stats\"][q][\"--\"]\n",
" \n",
" nb_mm = row[\"stats\"][\"10\"][\"--\"]\n",
" \n",
" if relative:\n",
" nb_eval = sum([row[\"stats\"][\"1\"][i] for i in [\"--\",\"-\",\"+\",\"++\"] ])\n",
" # return nb_mm / float(nb_eval*len(q_list))\n",
" return nb_mm / float(nb_eval)\n",
" else :\n",
" return nb_mm\n",
" \n",
"tmp = data_pd.apply(get_mm_per_row, axis=1)\n",
"\n",
"graph_data = [\n",
" go.Scatter(\n",
" x=tmp.sort_values().index,\n",
" y=tmp.sort_values(),\n",
" )\n",
"]\n",
"layout = go.Layout(\n",
" title=\"Pourcentage d'avis très négatif (--) sur l'appréciation finale de l'UV (question 10 des évaluations)\"\n",
")\n",
"\n",
"\n",
"fig = go.Figure(data=graph_data, layout=layout)\n",
"iplot(fig)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Remarques\n",
"\n",
"Pour la suite de l'analyse il est plus simple d'affecter une note numérique à chaque évaluation. Pour se faire il a été décidé d'utiliser la table de conversion _symétrique_ suivante :\n",
"\n",
"| Sigle | Valeur associée |\n",
"|-------|-----------------|\n",
"| ++ | +3 |\n",
"| + | +1 |\n",
"| - | -1 |\n",
"| -- | -3 |\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"list_answers = [\"--\",\"-\",\"+\",\"++\"]\n",
"list_coeffs = [-3,-1,1,3]\n",
"\n",
"def get_nb_eval(row):\n",
" return sum([row[\"stats\"][\"1\"][i] for i in list_answers])\n",
"\n",
"def get_mark_q(row, q): \n",
" if type(q) is int:\n",
" q = str(q)\n",
" return sum([row[\"stats\"][q][list_answers[i]] * list_coeffs[i] for i in range(len(list_coeffs))]) / get_nb_eval(row)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tmp = data_pd.apply((lambda r : get_mark_q(r,10)), axis=1)\n",
"\n",
"graph_data = [\n",
" go.Scatter(\n",
" x=tmp.sort_values(ascending = False).index,\n",
" y=tmp.sort_values(ascending = False),\n",
" )\n",
"]\n",
"\n",
"layout = go.Layout(\n",
" title=\"Visualisation de l'appréciation globale de chaque UV (question 10) sous forme de note moyenne\"\n",
")\n",
"\n",
"fig = go.Figure(data=graph_data, layout=layout)\n",
"iplot(fig)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Tweak css for displaying data \n",
"\n",
"from IPython.core.display import HTML\n",
"style = open('./style.css').read()\n",
"HTML(\"<style>\"+style+\"</style>\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
},
"toc": {
"base_numbering": 1,
"nav_menu": {
"height": "224px",
"width": "278px"
},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {
"height": "calc(100% - 180px)",
"left": "10px",
"top": "150px",
"width": "384px"
},
"toc_section_display": true,
"toc_window_display": true
}
},
"nbformat": 4,
"nbformat_minor": 2
}
html {
font-size: 62.5% !important;
}
body {
font-size: 1.5em !important;
/* currently ems cause chrome bug misinterpreting rems on body element */
line-height: 1.6 !important;
font-weight: 400 !important;
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif !important;
color: #222 !important;
}
div {
border-radius: 0px !important;
}
div.CodeMirror-sizer {
background: rgb(244, 244, 248) !important;
}
div.input_area {
background: rgb(244, 244, 248) !important;
}
div.out_prompt_overlay:hover {
background: rgb(244, 244, 248) !important;
}
div.input_prompt:hover {
background: rgb(244, 244, 248) !important;
}
h1,
h2,
h3,
h4,
h5,
h6 {
color: #333 !important;
margin-top: 0 !important;
margin-bottom: 2rem !important;
font-weight: 300 !important;
}
h1 {
font-size: 4.0rem !important;
line-height: 1.2 !important;
letter-spacing: -.1rem !important;
}
h2 {
font-size: 3.6rem !important;
line-height: 1.25 !important;
letter-spacing: -.1rem !important;
}
h3 {
font-size: 3.0rem !important;
line-height: 1.3 !important;
letter-spacing: -.1rem !important;
}
h4 {
font-size: 2.4rem !important;
line-height: 1.35 !important;
letter-spacing: -.08rem !important;
}
h5 {
font-size: 1.8rem !important;
line-height: 1.5 !important;
letter-spacing: -.05rem !important;
}
h6 {
font-size: 1.5rem !important;
line-height: 1.6 !important;
letter-spacing: 0 !important;
}
@media (min-width: 550px) {
h1 {
font-size: 5.0rem !important;
}
h2 {
font-size: 4.2rem !important;
}
h3 {
font-size: 3.6rem !important;
}
h4 {
font-size: 3.0rem !important;
}
h5 {
font-size: 2.4rem !important;
}
h6 {
font-size: 1.5rem !important;
}
}
p {
margin-top: 0 !important;
}
a {
color: #1EAEDB !important;
}
a:hover {
color: #0FA0CE !important;
}
code {
padding: .2rem .5rem !important;
margin: 0 .2rem !important;
font-size: 90% !important;
white-space: nowrap !important;
background: #F1F1F1 !important;
border: 1px solid #E1E1E1 !important;
border-radius: 4px !important;
}
pre>code {
display: block !important;
padding: 1rem 1.5rem !important;
white-space: pre !important;
}
button {
border-radius: 0px !important;
}
.navbar-inner {
background-image: none !important;
}
select,
textarea {
border-radius: 0px !important;
}
\ No newline at end of file
#Observatoire-Des-UVs
jupyter==1.0.0
plotly==2.6.0
cufflinks==0.12.1
pandas==0.22.0
numpy==1.14.2
jupyter_contrib_nbextensions==0.5.0
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment