Les scripts de création des données sont dans le dépot github notebook : http://nbviewer.ipython.org/github/philippechataignon/notebook/tree/master
In [76]:
st = pd.HDFStore('data/data.h5')
dc_clc = set(st.clc2006.index)
dc_euro = set(st.euro2014.index)
dc_ref = set(st.cog2014.index)
Toutes les communes issues de Corine Land Cover sont dans le code officiel géographique.
In [77]:
dc_clc - dc_ref
Out[77]:
Toutes les communes issues des résulats électoraux ne sont pas dans le code officiel géographique. Toutefois, on peut vérifier qu'il ne s'agit que des circonscriptions des français de l'étranger (en fait non, cf ci-dessous).
Errata : suite à tweet de @vallettea et @louisdorard, il y a également les circonscriptions DOM/TOM :
if x in set(["ZA", "ZB", "ZC", "ZD", "ZS"]): #guadeloupe, martinique, guyanne, reunion, St pierre et miquelon
return "97"
elif x in set(["ZP", "ZN"]): #polynesie, nouvelle caledonie
return "98"
else:
return as_string(x)
In [78]:
" ".join(sorted(dc_euro - dc_ref))
Out[78]:
La gestion de la géographie adminstrative est toujours un problème à règler lorsqu'on travaille avec plusieurs sources. Ici, on part du fichier historique des communes disponible sur le site de l'INSEE, qui fournit pour chaque commune non active son pôle, par exemple la commune vers laquelle elle a fusionnée. Pur les communes actives, et contrairement à ce que fait l'INSEE, on a repris le code de la commune dans le pôle, ce qui fait que l'on peut systématiquement utiliser le passage code commune vers pôle pour ramener les informations sur une géographie actuelle.
Pour chaque table de données, dans un permier temps, on récupère l'information sur le pôle dans les tables de donnée en faisant une jointure. Puis on supprime les lignes où pole est à null. Ensuite, pole devient le nouvel index du DataFrame. On peut vérifier qu'il n'est pas unique et on le rend unique en sommant toutes les variables.
In [79]:
p = st.cog2014.pole
euro2014 = st.euro2014.join(p)
euro2014.dropna(subset=['pole'], inplace=True)
euro2014.set_index('pole', inplace=True)
euro2014.index.is_unique
euro = euro2014.groupby(euro2014.index).sum()
In [80]:
clc2006 = st.clc2006.join(p)
clc2006.dropna(subset=['pole'], inplace=True)
clc2006.set_index('pole',inplace=True)
clc2006.index.is_unique
clc = clc2006.groupby(clc2006.index).sum()
Maintenant que la géographie a été traitée, on peut rapprocher les données par code commune (en fait pole). On nettoie les lignes avec dans valeurs manquantes.
In [81]:
w = euro.join(clc)
w.dropna(inplace=True)
w.head()
# w.to_csv('data/etude_clc_euro.tsv', delimiter='\t')
Out[81]:
On va calculer la proportion pour les différents type de terrains dans les colonnes préfixées par p. De même, pour le vote FN, on s'intéresse au % par rapport aux exprimés.
In [82]:
import statsmodels.api as sm
clc = [u'111', u'112', u'121', u'122', u'123', u'124', u'131', u'132', u'133', u'141',
u'142', u'211', u'212', u'213', u'221', u'222', u'223', u'231', u'241', u'242',
u'243', u'244', u'311', u'312', u'313', u'321', u'322', u'323', u'324', u'331',
u'332', u'333', u'334', u'335',
u'411', u'412', u'421', u'422', u'423', u'511', u'512', u'521', u'522', u'523']
pclc = ['p' + l for l in clc]
w[pclc] = w[clc].div(w[clc].sum(axis=1), axis=0)*100
w['pfn'] = w['LFN'] / w['Exprimés'] * 100
Pour finir, on recalcule les niveau 1 et 2 de la nomenclature CLC sous forme de MultiIndex.
In [83]:
clc2 = [ (x[:2], x[:3], x) for x in pclc]
iclc2 = pd.MultiIndex.from_tuples(clc2)
w1 = pd.DataFrame(w[pclc].values, columns=iclc2, index=w.index)
X = w1.sum(level=1, axis=1)
y = w.pfn
# Fit regression model
results = sm.OLS(y, X).fit()
# Inspect the results
print results.summary()
La valeur des coefficients de la regression indique la propension de chaque type de sol à augmenter le vote FN. C'est la catégorie "mines, décharges et chantiers" qui arrive en tête, suivie des zones humides intérieures et des eaux maritimes, c'est-à-dire le littoral. Seule la présence d'espaces verts a un impact négatif.
In [84]:
lib = pd.read_csv('data/lib_clc2.csv', delimiter='\t', index_col=[0])
r = results.params
pos = arange(len(r))
plt.figure(figsize=(14,8))
plt.yticks(arange(len(r)), lib.lib)
plt.barh(pos, r, align='center')
plt.show()