Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…ServicePublic into gh-pages
  • Loading branch information
AlexisEidelman committed Mar 2, 2017
2 parents 3f6e6bd + 8b4a08a commit c357eea
Show file tree
Hide file tree
Showing 7 changed files with 355 additions and 24 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ Toute contribution est la bienvenue !

Je voudrais aussi permettre de visualiser les évolutions : quelles organisations changent et quand ?
Pour cela, il faudrait un historique des données.

* Ajouter les données de la base SIRENE pour enrichir la base.

On trouve ici un [exemple](http://data.enseignementsup-recherche.gouv.fr/pages/explorer/?sort=modified&refine.publisher=Minist%C3%A8re%20de%20l%27%C3%89ducation%20nationale,%20de%20l%27Enseignement%20sup%C3%A9rieur%20et%20de%20la%20Recherche&q=siret) d'administrations avec un siret (à étudier).

Voir comment les données sont dans le fichier SIRENE. Est-ce que l'on peut faire un lien avec les données.
Binary file added SIRENE/HackathonSirene.odp
Binary file not shown.
71 changes: 71 additions & 0 deletions SIRENE/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
Ce dossier rassemble les informations sur les
service public telles que contenu dans la base Sirene.

# Projet

La base Sirene est une donnée de référence. Ce n'est pas pour autant qu'elle se suffit à elle-même. En effet, elle a des liens avec au moins deux autres données de référence : la **base adresses nationale** et l'**annuaire des services publics**.

Dans ce repo nous nous intéresserons essentiellement au lien entre la base SIRENE et l'annuaire des services publics.

Relier les entrées de la base Sirene avec les données de l'annuaire de l'administration publiées. Sont-elles cohérentes entre elles ? Lesquelles font référence ? Comment une modification de l'une des deux bases doit se propager à l'autre ?


## Faisabilité

Les données existent. En effet sur [cette page](http://www.insee.fr/fr/methodes/default.asp?page=definitions/sirene-secteur-public.htm) du site de l'Insee, on trouve le passage suivant :

>C'est en 1983 que la mission d'immatriculation au répertoire a été étendue au secteur public. L'unité SIREN est appelée organisme lorsqu'elle relève du secteur non marchand. Elle couvre donc normalement les personnes morales que constituent l'État, les collectivités territoriales et les établissements publics.
>
>Toutefois, certaines institutions et certains services de l'État, bien que non dotés de la personnalité juridique, sont identifiés comme organismes lorsqu'ils jouissent d'une « quasi-personnalité juridique ». C'est le cas des autorités constitutionnelles, des autorités administratives indépendantes, des ministères, des directions d'administration centrale ainsi que des services extérieurs, territorialisés ou non.
>
>L'unité SIRET de type établissement correspond soit à une implantation géographique distincte où s'exerce une activité, soit à une implantation géographique pour laquelle il existe un budget annexe. Ceci signifie que, contrairement au secteur privé, à une même adresse il peut exister plusieurs numéros SIRET pour un même numéro SIREN.


## Méthode

### Comment repérer les administrations publiques dans la base Sirene ?

Plusieurs idées :

* utiliser le code [naf](http://www.insee.fr/fr/methodes/default.asp?page=nomenclatures/agregatnaf2008/agregatnaf2008.htm) et en particulier [celles commençant par 84](http://www.insee.fr/fr/methodes/default.asp?page=nomenclatures/naf2008/n1_o.htm)
* utiliser [la nomenclature des catégories juridiques](http://www.insee.fr/fr/methodes/default.asp?page=nomenclatures/cj/cj-arbre.htm)

### Comment faire le lien entre SIRENE et Annuaire ?

La meilleure idée semble d'utiliser les noms des entités. On remarquera tout de suite que les formats sont différents (majuscules non accentuées dans un cas, simili Camel Case accentué dans l'autre).

Est-ce que les adresses peuvent aider ?

D'autres idées ?

### Quel est le meilleure agencement des données de SIRENE et de l'annuaire ?

Des questions sont ouvertes :
* Comment gère-t-on les changements de noms ?
* Que faire des incohérences actuelles (s'il y en a).
* Quelle(s) adresse(s) doit-être conservée(s) ? Celle de l'annuaire ? Celle de SIRENE ?
* ...


### Autres choses

* Regarder les SIREN disparu des entités publiques (mais on a seulement les établissements actifs).
* Lorsqu'on a plusieurs établissements, est-ce que cela correspond à une arborescence de l'annuaire ?


## Notes:

### Mise à jour des données de l'administration dans SIRENE.

Il y a trois fonctions publiques :
* Hospitalière : on essaie d'être cohérent avec FINESS (on ne rentre pas d'unité dans SIRENE qui n'a pas de numéro Finess). Il y a parfois plusieurs lignes quand il y a plusieurs lignes dans FINESS quand il y a plusieurs services mais pas dans SIRENE.
* Les collectivités territoriales : il y a des obligations fortes pour qu'elles utilisent SIREN, SIRET parce qu'elles emploient et passent des contrats. Les prefectures envoient les infos. Pas de gestions automatiques.
* La Dila (a priori) devrait transmettre automatiquement mais ça se fait mal. Rermarque: tout le monde doit avoir un SIREN/SIRET pour utiliser chorus.
Les services déconcentrés, c'est soit les prefectures, soit les administrations elle-même.

Dans la fonction publique d'Etat, la personnalité juridique c'est l'Etat donc dans SIRENE, c'est par convention qu'on attribue à des SIREN qui va à des ordonnateurs.

Les infos récupérées par l'Insee pour la base SIRENE, c'est le Nom, l'adresse, le ministère de tutelle.


39 changes: 39 additions & 0 deletions SIRENE/read_Sirene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
"""
@author: aeidelman
"""

import os
import pandas as pd

path = '/home/sgmap/data/SIRENE'

# avantage
path_file = os.path.join(path,
'sirc-266_266_13705_201606_L_P_20161010_121909418-secondtry.csv')

tab = pd.read_csv(path_file, sep=';', nrows=100000,
encoding='cp1252', #iso-8859-15
# usecols = categorical_vars + ['avant_montant_ttc']
)

assert all(tab.APET700.str.len() == 5)

# public = tab[tab['NJ'].astype(str).str[0] == '7']
# print(len(public))


#av['year'] = av['avant_date_signature'].str[6:]
iter_csv = pd.read_csv(path_file, sep=';',
encoding='cp1252',
iterator=True,
chunksize=100000)

df = pd.concat([tab[tab['NJ'].astype(str).str[0].isin(['4','7'])]
for tab in iter_csv])

path_output = os.path.join(path, 'sirene_NJ_4_et_7.csv')
df.to_csv(path_output, sep=';',
encoding='cp1252',
iterator=True,
index=False)
143 changes: 119 additions & 24 deletions diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,134 @@
Etudie les differences d'une version de l'annuaire à l'autre
TODO: retirer les updates_the de l'analyse, ils redondent
"""

import os
import pandas as pd

files = os.listdir('csv')
files.sort()
from load import load_csv

name1, name2 = files[:2]

def load(name):
file = os.path.join('csv', name)
tab = pd.read_csv(file)
tab.drop('_merge', axis=1, inplace=True)
return tab
def diff_csv(name1, name2, verbose=True, keep=None, drop=None):
''' effectue la différence des deux csv
retourne les lignes pour lesquelles les informations
dans '''
tab1 = load_csv(name1, drop, keep)
tab2 = load_csv(name2, drop, keep)

merge = tab1.merge(tab2, on = ['index', 'parent'],
indicator=True, how='outer')

if verbose:
print(merge._merge.value_counts())

tab1 = load(name1)
tab2 = load(name2)
cols_x = [col for col in merge.columns if col[-2:] == '_x']
cols_y = [col for col in merge.columns if col[-2:] == '_y']

merge = tab1.merge(tab2, on = ['index', 'parent'],
indicator=True, how='outer')

merge._merge.value_counts()
merge_y = merge[cols_y].rename(columns=dict(x for x in zip(cols_y, cols_x)))
similar = merge[cols_x] == merge_y
differents = ~similar.all(axis=1)
if verbose:
print("il y a {} differences sur {} entités".format(
sum(differents),
len(merge))
)

if verbose:
print((~similar).sum())

diff = merge[differents]
diff[cols_x] = diff[cols_x].mask(similar)
diff[cols_y] = diff[cols_y].mask(similar)
diff[cols_x] += ' -> ' + merge_y[differents]
return diff[['index', 'parent'] + cols_x + ['_merge']]


def revient_a_la_valeur_initiale(name1, name2, name3, keep=None, drop=None):
''' regarde si les valeurs sont les mêmes dans name1 et name3 alors
qu'elles sont différentes dans name2
'''
tab1 = load_csv(name1, drop, keep)
tab2 = load_csv(name2, drop, keep)
tab3 = load_csv(name2, drop, keep)

merge = tab1.merge(tab2, on = ['index', 'parent']). \
merge(tab3, on = ['index', 'parent'])


cols_x = [col for col in merge.columns if col[-2:] == '_x']
cols_y = [col for col in merge.columns if col[-2:] == '_y']
cols_z = [col[:-2] for col in cols_x ]

merge_y = merge[cols_y].rename(columns=dict(x for x in zip(cols_y, cols_x)))
merge_z = merge[cols_z].rename(columns=dict(x for x in zip(cols_z, cols_x)))
similar_x_z = merge[cols_x] == merge_z
different_x_y = merge[cols_x] != merge_y
similar_y_z = merge_y == merge_z
return similar_x_z & different_x_y
#matchees = merge[merge._merge == 'both']
#del matchees['_merge']
#
#matchees.fillna('nan', inplace=True)
#
#
#return differents

if __name__ == '__main__':
# test = revient_a_la_valeur_initiale('annuaire_20161019.csv',
# 'annuaire_20161022.csv',
# 'annuaire_20161026.csv')
#
basic_drop = ['http://www.mondeca.com/system/basicontology#updated_the',
'an/telecopie', 'an/telephone']
keep_for_sirene = ['index', 'parent',
'an/adressePhysiqueCodePostal',
'an/adressePhysiqueVille',
'http://www.w3.org/2000/01/rdf-schema#label',
]
differents1 = diff_csv('annuaire_20161022.csv', 'annuaire_20161026.csv',
keep=keep_for_sirene)
differents2 = diff_csv('annuaire_20161026.csv', 'annuaire_20161102.csv',
keep=keep_for_sirene)
differents3 = diff_csv('annuaire_20161022.csv', 'annuaire_20161102.csv',
keep=keep_for_sirene)

diff1 = merge[merge._merge != 'both']
# for col in differents3.columns:
# if differents1[col].nunique() > 5:
# print(differents1[col].value_counts().head())
# print(differents2[col].value_counts().head())
# print('\n')
#
# for tab in [differents1, differents2, differents3]:
# print('en tout on a {} changement'.format(len(tab)))
# changements = tab.notnull().sum()
# changements.drop(['parent', 'index'], inplace=True)
# changements.sort_values(ascending=False, inplace=True)
# print(changements.head(7))

diff_6_mois = diff_csv('annuaire_20160702.csv', 'annuaire_20161112.csv',
keep=keep_for_sirene)
both = diff_6_mois[diff_6_mois._merge == 'both']
diff_label = both2['http://www.w3.org/2000/01/rdf-schema#label_x']
diff_label = diff_label[diff_label.notnull()]

result = ''
for changement in diff_label.values:
chgt = changement
chgt = chgt.replace('->','\n \t devient \n')
result += chgt + '\n --- \n'

matchees = merge[merge._merge == 'both']
cols_1 = [col for col in matchees.columns if col[-2:] == '_x']
with open('chgt_noms_matcheds.txt', 'w') as f:
f.write(result)

del matchees['_merge']
matchees.fillna('nan', inplace=True)
for col in cols_1:
nb_diff = sum(matchees[col] != matchees[col[:-1] + 'y'])
if nb_diff > 0:
print(col)
print(nb_diff)
#Il y a des choses étonnantes dans les adresses des sites web par exemple.
#http://www.defense.gouv.fr/dga -> http://www.ixarm.com 39
#http://www.education.gouv.fr -> http://www.enseignementsup-recherche.gouv.fr 37
#http://www.enseignementsup-recherche.gouv.fr -> http://www.education.gouv.fr 35
#http://www.ixarm.com -> http://www.defense.gouv.fr/dga 31
#
#http://www.education.gouv.fr -> http://www.enseignementsup-recherche.gouv.fr 40
#http://www.ixarm.com -> http://www.defense.gouv.fr/dga 38
#http://www.defense.gouv.fr/dga -> http://www.ixarm.com 35
#http://www.enseignementsup-recherche.gouv.fr -> http://www.education.gouv.fr 34
78 changes: 78 additions & 0 deletions diff_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 10 14:31:31 2016
@author: aeidelman
"""

import os
import json

files = os.listdir('json')
files.sort()
names = [file[:-4] for file in files]

for k in range(1,len(files) - 1):
file1 = files[k]
f = open('json/' + file1)
v1 = json.load(f)

file2 = files[k+1]
f = open('json/' + file2)
v2 = json.load(f)




# difference de keys...
set1 = set(v1)
set2 = set(v2)
dans2_pas_dans1 = set2 - set1
dans1_pas_dans2 = set1 - set2

# la différence entre tous les éléments
differences = list()
for entite in v1.keys():
if entite in v2.keys():
dict1 = v1[entite]
dict2 = v2[entite]

keys1 = set(dict1.keys())
keys2 = set(dict2.keys())

for champs in keys1 & keys2:
value1 = dict1[champs]
value2 = dict2[champs]
if value2 != value1:
differences += [(entite, champs,
value1, value2)]

for champs in keys2 - keys1:
differences += [(entite, champs,
'', dict2[champs])]

for champs in keys1 - keys2:
differences += [(entite, champs,
dict1[champs], '')]

#import pdb
#pdb.set_trace()

# analyse des différences
import pandas as pd
diff_df = pd.DataFrame(differences)
changes = diff_df[2] + '\n devient \n ' + diff_df[3]

print(diff_df[0].value_counts().head())
print(diff_df[1].value_counts())

for row in changes.value_counts().head(10).items():
print('On a {0} changements où \n {1} \n'.format(row[1], row[0]))

un_pb = 'df/Ministeres_Ministere_de_l_economie_de_l_industrie_et_de_l_emploi'
diff_df[diff_df[3] == un_pb]

# inversions
inversion = (diff_df[2] + diff_df[3]).isin(diff_df[3] + diff_df[2])


Loading

0 comments on commit c357eea

Please sign in to comment.