Commit 84d36fdc authored by gossa's avatar gossa

Etudes de la campagne d'emplois 2019

parent 346d00d5
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
#!/bin/R
# DataSets :
# galaxie https://www.galaxie.enseignementsup-recherche.gouv.fr/ensup/ListesPostesPublies/Emplois_publies_TrieParCorps.html
# (updateEmploi.sh télécharge et formate ces données)
# DataESR https://data.enseignementsup-recherche.gouv.fr/explore/dataset/fr-esr-enseignants-titulaires-esr-public/
library(ggplot2)
library(plyr)
library(tidyverse)
library(ggrepel)
# Approximation des sections CNU correspondant aux flilières en tension
section.cnu.en.tension = c("74","70","18","16","01","02","03","71")
# Chargement des données Galaxie
df.emplois.2018 <- read.table("emplois.ec.2018.csv",header=TRUE, sep=",", quote='"')
df.emplois.2018$Rentrée <- 2018
df.emplois.2019 <- read.table("emplois.ec.2019.csv",header=TRUE, sep=",", quote='"')
df.emplois.2019$Rentrée <- 2019
df.emplois <- rbind(df.emplois.2018,df.emplois.2019)
df.emplois$Section <- sprintf("%02d",df.emplois$Section)
df.emplois$en.tension <- df.emplois$Section %in% section.cnu.en.tension
# Plots sur Galaxie seulement
png("emplois.ec.2019.png", width=1024)
ggplot(subset(df.emplois,Rentrée==2019),
aes(x=Section, fill=Corps, colour=en.tension)) +
stat_count() +
ylab("Nombre d'emplois publiés à la session synchronisée") + xlab("Section CNU") +
scale_colour_manual(values=c("#FFFFFF", "#FF0000"), name="Filière", labels=c("Normale", "En tension")) +
scale_fill_discrete(name="Corps", labels=c("MCF", "PR")) +
theme(axis.title=element_text(size=16)) +
ggtitle("Nombre d'emplois par section CNU à la session synchronisée 2019")
dev.off()
png("emplois.ec.png", width=1024)
ggplot(df.emplois,
aes(x=Rentrée, fill=Corps, colour=en.tension)) +
stat_count() +
facet_grid(. ~ Section) +
ylab("Nombre d'emplois publiés aux sessions synchronisées 2018 et 2019") + xlab("Section CNU") +
theme(axis.title=element_text(size=16),
axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank()) +
scale_colour_manual(values=c("#FFFFFF", "#FF0000"), name="Filière", labels=c("Normale", "En tension")) +
scale_fill_discrete(name="Corps", labels=c("MCF", "PR"))
dev.off()
png("emploi.ec.png", width=1024)
ggplot(df.emplois,
aes(x=Etablissement, fill=Corps, colour=en.tension)) +
stat_count() +
coord_flip() +
ylab("Nombre d'emplois publiés aux sessions synchronisées 2018 et 2019") + xlab("Section CNU") +
theme(axis.text.x = element_text(angle = 90, hjust = 1),
axis.text.y = element_text(angle = 90)) +
scale_colour_manual(values=c("#FFFFFF", "#FF0000"), name="Filière", labels=c("Normale", "En tension")) +
scale_fill_discrete(name="Corps", labels=c("MCF", "PR"))
dev.off()
# Chargement des données DataESR
df.enst.raw <- read.table("fr-esr-enseignants-titulaires-esr-public.csv",
header=TRUE, sep=';', quote='"')
df.enst.2017 <- subset(df.enst.raw, Rentrée == 2017 & Code.categorie.personnels != "AM2D")
df.enst.2017$code_section_cnu <- sprintf("%02d",df.enst.2017$code_section_cnu)
df.enst.etab <- aggregate(
effectif ~ Établissement + Identifiant.établissement + Code.categorie.personnels + Categorie.de.personnels,
df.enst.2017, sum)
# plots sur galaxie + DataESR
## Par section CNU
df.emplois.cnu <- plyr::count(subset(df.emplois,Rentrée==2019), c('Section','en.tension','Corps'))
df.emplois.cnu <- spread(df.emplois.cnu,Corps,freq, fill=0)
colnames(df.emplois.cnu) <- c("Section","en.tension","emplois.MCF","emplois.PR")
df.enst.cnu <- aggregate(
effectif ~ code_section_cnu + Code.categorie.personnels,
df.enst.2017, sum)
df.enst.cnu <- spread(df.enst.cnu,Code.categorie.personnels,effectif, fill=0)
colnames(df.enst.cnu) <- c("Section","effectifs.MCF","effectifs.PR")
df.cnu <- merge(df.emplois.cnu,df.enst.cnu)
df.cnu$promotions <- df.cnu$emplois.PR / df.cnu$effectifs.MCF
df.cnu$renouvellement <- df.cnu$emplois.MCF / (df.cnu$effectifs.MCF+df.cnu$effectifs.PR)
### Plot
png("emplois.cnu.png", height=640)
ggplot(df.cnu,aes(x=reorder(Section,Section))) +
geom_bar(aes(y=emplois.PR,fill="pr"), stat="identity") +
geom_bar(aes(y=-emplois.MCF, fill="mcf"), stat="identity") +
coord_flip() +
scale_fill_manual(
values=c("red", "blue"), name="",
labels=c("emplois MCF","emplois PR"),
breaks=c("mcf","pr")) +
scale_y_continuous(labels = c("80","40","0","40")) +
ylab("<- MCF / PR ->") +
xlab("Section CNU") +
theme(legend.position="top", plot.title = element_text(hjust = 0.5)) +
ggtitle("Nombre d'emplois par section CNU la session synchronisée 2019")
dev.off()
png("effectifs.cnu.png", height=640)
ggplot(df.cnu,aes(x=reorder(Section,Section))) +
geom_bar(aes(y=effectifs.PR,fill="pr"), stat="identity") +
geom_bar(aes(y=-effectifs.MCF, fill="mcf"), stat="identity") +
coord_flip() +
scale_fill_manual(
values=c("red", "blue"), name="",
labels=c("effectifs MCF","Effectifs PR"),
breaks=c("mcf","pr")) +
scale_y_continuous(labels = c("3000","2000","1000","0","1000")) +
ylab("<- MCF / PR ->") +
xlab("Section CNU") +
theme(legend.position="top", plot.title = element_text(hjust = 0.5)) +
ggtitle("Effectifs par section CNU en 2017")
dev.off()
syc_breaks<-seq(-0.05,0.05,0.02)
syc_labels<-paste(abs(syc_breaks)*100,"%\n",round(abs(1/syc_breaks))," ans",sep='')
syc_repr <- scale_y_continuous(breaks=syc_breaks, labels=syc_labels)
sfm_repr <- scale_fill_manual(values=c("red", "blue"), name="",
breaks=c("renouvellement","promotions"),
labels=c("Renouvellement = emplois MCF / effectifs MCF+PR",
"Promotions = emplois PR/effectifs MCF"))
png("promovsrenouv.cnu.png", height=640)
ggplot(df.cnu,aes(x=reorder(Section,Section))) +
geom_bar(aes(y=promotions,fill="promotions"), stat="identity") +
geom_bar(aes(y=-renouvellement, fill="renouvellement"), stat="identity") +
coord_flip() +
syc_repr + sfm_repr +
ylab("<- Renouvellement / Promotions ->") +
xlab("Section CNU") +
theme(legend.position="top", plot.title = element_text(hjust = 0.5)) +
ggtitle("Promotions et renouvellement par section CNU")
dev.off()
png("promovsrenouv.sort.cnu.png", height=640)
ggplot(df.cnu,aes(x=reorder(Section,-renouvellement))) +
geom_bar(aes(y=promotions,fill="promotions"), stat="identity") +
geom_bar(aes(y=-renouvellement, fill="renouvellement"), stat="identity") +
coord_flip() +
syc_repr + sfm_repr +
ylab("<- Renouvellement / Promotions ->") +
xlab("Section CNU") +
theme(legend.position="top", plot.title = element_text(hjust = 0.5)) +
ggtitle("Promotions et renouvellement par section CNU")
dev.off()
png("promovsrenouv.map.cnu.png")
ggplot(df.cnu,aes(y=promotions, x=renouvellement, colour=en.tension)) +
geom_point() + geom_label_repel(aes(label=Section)) +
ylab("Promotions : emplois PR/effectifs MCF") +
xlab("Renouvellement : emplois MCF / effectifs MCF+PR") +
scale_colour_manual(values=c("blue", "red"), name="Filière",
labels=c("Normale", "En Tension")) +
coord_equal(xlim=c(0,0.06),ylim=c(0,0.06)) +
scale_y_continuous(breaks=syc_breaks, labels=syc_labels) +
scale_x_continuous(breaks=syc_breaks, labels=syc_labels) +
theme(plot.title = element_text(hjust = 0.5)) +
ggtitle("Promotions vs. Renouvellement dans les sections CNU")
dev.off()
## Par établissement
df.emplois.etab <- plyr::count(subset(df.emplois,Rentrée==2019), c('UAI','Corps'))
df.emplois.etab <- spread(df.emplois.etab,Corps,freq, fill=0,convert=TRUE)
colnames(df.emplois.etab) <- c("UAI","emplois.MCF","emplois.PR")
df.enst.etab <- aggregate(
effectif ~ Établissement + Identifiant.établissement + Code.categorie.personnels,
df.enst.2017, sum)
df.enst.etab <- spread(df.enst.etab,Code.categorie.personnels,effectif,fill=0,convert=TRUE)
colnames(df.enst.etab) <- c("Etablissement","UAI","effectifs.MCF","effectifs.PR")
df.etab <- merge(df.emplois.etab,df.enst.etab)
df.etab$promotions <- df.etab$emplois.PR / df.etab$effectifs.MCF
df.etab$renouvellement <- df.etab$emplois.MCF / (df.etab$effectifs.MCF+df.etab$effectifs.PR)
# Réduction de l'échantillon à un minimum de postes
df.etab <- subset(df.etab, (emplois.MCF+emplois.PR) > 5)
### plots
png("emplois.etab.png", height=1024)
ggplot(df.etab,aes(x=reorder(Etablissement,emplois.MCF+emplois.PR))) +
geom_bar(aes(y=emplois.PR,fill="pr"), stat="identity") +
geom_bar(aes(y=-emplois.MCF, fill="mcf"), stat="identity") +
coord_flip() +
scale_fill_manual(
values=c("red", "blue"), name="",
labels=c("emplois MCF","emplois PR"),
breaks=c("mcf","pr")) +
scale_y_continuous(labels = c("40","20","0","20")) +
ylab("<- MCF / PR ->") +
xlab("Etablissement") +
theme(legend.position="top", plot.title = element_text(hjust = 0.5)) +
ggtitle("Emplois par établissement à la session sychronisée 2019")
dev.off()
png("effectifs.etab.png", height=640)
ggplot(df.etab,aes(x=reorder(Etablissement,emplois.MCF+emplois.PR))) +
geom_bar(aes(y=effectifs.PR,fill="pr"), stat="identity") +
geom_bar(aes(y=-effectifs.MCF, fill="mcf"), stat="identity") +
coord_flip() +
scale_fill_manual(
values=c("red", "blue"), name="",
labels=c("effectifs MCF","effectifs PR"),
breaks=c("mcf","pr")) +
scale_y_continuous(labels = c("1500","1000","500","0","500","1000")) +
ylab("<- MCF / PR ->") +
xlab("Etablissement") +
theme(legend.position="top", plot.title = element_text(hjust = 0.5)) +
ggtitle("Effectifs par établissement à la session sychronisée en 2017")
dev.off()
syc_breaks<-seq(-0.09,0.15,0.02)
syc_labels<-paste(abs(syc_breaks)*100,"%\n",round(abs(1/syc_breaks))," ans",sep='')
syc_repr <- scale_y_continuous(breaks=syc_breaks, labels=syc_labels)
png("promovsrenouv.etab.png", height=1024)
ggplot(df.etab,aes(x=reorder(Etablissement,emplois.MCF+emplois.PR))) +
geom_bar(aes(y=promotions,fill="promotions"), stat="identity") +
geom_bar(aes(y=-renouvellement, fill="renouvellement"), stat="identity") +
coord_flip() +
sfm_repr + syc_repr +
ylab("<- Renouvellement / Promotions ->") +
xlab("Etablissement") +
theme(legend.position="top", plot.title = element_text(hjust = 0.5)) +
ggtitle("Promotions et renouvellement par établissement à la session sychronisée en 2017")
dev.off()
png("promovsrenouv.etab.sortpromo.png", height=1024)
ggplot(df.etab,aes(x=reorder(Etablissement,promotions))) +
geom_bar(aes(y=promotions,fill="promotions"), stat="identity") +
geom_bar(aes(y=-renouvellement, fill="renouvellement"), stat="identity") +
coord_flip() +
sfm_repr + syc_repr +
ylab("<- Renouvellement / Promotions ->") +
xlab("Etablissement") +
theme(legend.position="top", plot.title = element_text(hjust = 0.5)) +
ggtitle("Classement des établissements qui promeuvent le plus vite")
dev.off()
png("promovsrenouv.etab.sortrenouv.png", height=1024)
ggplot(df.etab,aes(x=reorder(Etablissement,renouvellement))) +
geom_bar(aes(y=promotions,fill="promotions"), stat="identity") +
geom_bar(aes(y=-renouvellement, fill="renouvellement"), stat="identity") +
coord_flip() +
sfm_repr + syc_repr +
ylab("<- Renouvellement / Promotions ->") +
xlab("Etablissement") +
theme(legend.position="top", plot.title = element_text(hjust = 0.5)) +
ggtitle("Classement des établissements qui se renouvellent le plus vite")
dev.off()
This diff is collapsed.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#Richard's html2csv converter
#rbarnes@umn.edu
#modified by gossa@unistra.fr
#
from bs4 import BeautifulSoup
import sys
import csv
import argparse
parser = argparse.ArgumentParser(description='Reads in an HTML and attempts to convert all tables into CSV files.')
parser.add_argument('--delimiter', '-d', action='store', default=',',help="Character with which to separate CSV columns")
parser.add_argument('--quotechar', '-q', action='store', default='"',help="Character within which to nest CSV text")
parser.add_argument('filename',nargs="?",help="HTML file from which to extract tables")
args = parser.parse_args()
if sys.stdin.isatty() and not args.filename:
parser.print_help()
sys.exit(-1)
elif not sys.stdin.isatty():
args.filename = sys.stdin
else:
args.filename = open(sys.argv[1],'r')
print("Opening file")
fin = args.filename.read()
print("Parsing file")
soup = BeautifulSoup(fin,"html.parser")
print("Preemptively removing unnecessary tags")
[s.extract() for s in soup('script')]
print("CSVing file")
tablecount = -1
for table in soup.findAll("table"):
tablecount += 1
print("Processing Table #%d" % (tablecount))
with open(sys.argv[1]+str(tablecount)+'.csv', 'w', newline='') as csvfile:
fout = csv.writer(csvfile, delimiter=args.delimiter, quotechar=args.quotechar, quoting=csv.QUOTE_MINIMAL)
for row in table.findAll('tr'):
cols = row.findAll(['td','th'])
if cols:
cols = [str(x.text).strip().replace('\n','') for x in cols]
fout.writerow(cols)
#!/bin/sh
#Télécharge la liste des postes EC sur galaxy
#Corrige à l'arrache le html
#Converti en csv et nettoie les noms de fichers
RENTREE="2019"
WD=$PWD
cd /tmp
wget https://www.galaxie.enseignementsup-recherche.gouv.fr/ensup/ListesPostesPublies/Emplois_publies_TrieParCorps.html
cat Emplois_publies_TrieParCorps.html | sed 's/<th /<td /' > Emplois_publies_TrieParCorps.$RENTREE.html
$WD/html2csv.py Emplois_publies_TrieParCorps.$RENTREE.html
cp Emplois_publies_TrieParCorps.$RENTREE.html $WD
cp Emplois_publies_TrieParCorps.$RENTREE.html1.csv $WD/emplois.ec.$RENTREE.csv
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