<jupyter_start><jupyter_text>Analyse de données Grand Paris Sud Cette page présente une analyse de données libres issues du [portail Open Data de Grand Paris Sud](https://data.grandparissud.fr/pages/accueil/), du [site de l'INSEE](https://www.insee.fr/fr/accueil) et d'[OpenDataSoft](https://public.opendatasoft.com/explore/?sort=modified).La page met quelques minutes pour se charger entièrement, merci d'attendre que le chargement soit terminé (petite roue en haut à droite) avant de jouer avec les graphes interactifs.Auteur : [<NAME>](mailto:<EMAIL>), Engie<jupyter_code>import json
import pandas as pd
import numpy as np
from ipyleaflet import Map, basemaps, basemap_to_tiles, Marker, Choropleth, Icon
from branca.colormap import linear
from bqplot import (
    LogScale, LinearScale, OrdinalColorScale, ColorScale,
    Axis, Scatter, Lines, CATEGORY10, Label, Figure, Tooltip
)
from ipywidgets import HBox, VBox, IntSlider, Play, jslink, ToggleButtons, Layout
pd.set_option('display.max_colwidth', -1)
commune_PGS = ["91182", 
               "91228", 
               "91086", 
               "77067", 
               "77122", 
               "91174", 
               "91225", 
               "91286", 
               "91179", 
               "77251", 
               "91340", 
               "77296", 
               "91435", 
               "77326", 
               "77384", 
               "91521", 
               "91553", 
               "91573", 
               "91577", 
               "77445", 
               "91600", 
               "91617", 
               "77495", 
               "91659"]
initial_year = 1975
final_year = 2015
# spheres productive et présentielle par communes
spheres = pd.read_excel('Spheres_Donnees_communales_1975_2015_Geo2017.xls', sheet_name='DONNEES')
# pop par communes
pop = pd.read_csv('historique-des-populations-legales-2.csv', sep=',')
spheres.drop(range(7), inplace=True)
spheres.drop([8], inplace=True)
spheres.columns = spheres.iloc[0]
spheres.drop([7], inplace=True)
spheres.set_index('Code', inplace = True)
spheres.columns.name = ''
spheres = spheres.loc[spheres.index.isin(commune_PGS)]
spheres.drop(['Région', 'Aire urbaine', "Taille de \nl'aire urbaine\n(en emploi)"], axis=1, inplace=True)
def transform(data, nom):
    x_range = np.arange(1975, 2016, 1.)
    xp = [1975, 1982, 1990, 1999, 2010, 2015]
    yp = [data[nom + ' ' + str(annee)] for annee in xp]
    return np.interp(x_range, xp, yp)
for nom in ['Emploi total', 'Sphère productive', 'Sphère présentielle']:
    spheres[nom] = spheres.apply(transform, axis=1, nom=nom)
def get_pop(spheres_row, pop_data):
    x_range = np.arange(1975, 2016, 1.)
    xp = np.concatenate((np.array([1975., 1982., 1990., 1999.]), np.arange(2006, 2016, 1.)))
    yp = [int(pop_data[(pop_data["Code INSEE"] == int(spheres_row.name)) & (pop_data["Année"] == annee)]['Population municipale']) for annee in xp]
    return np.interp(x_range, xp, yp)
spheres['Population'] = spheres.apply(get_pop, axis=1, pop_data=pop)
prod_min, prod_max = np.min(spheres['Sphère productive'].apply(np.min)), np.max(spheres['Sphère productive'].apply(np.max))
pres_min, pres_max = np.min(spheres['Sphère présentielle'].apply(np.min)), np.max(spheres['Sphère présentielle'].apply(np.max))
pop_min, pop_max = np.min(spheres['Emploi total'].apply(np.min)), np.max(spheres['Emploi total'].apply(np.max))
def get_data(year):
    year_index = year - 1975
    prod = spheres['Sphère productive'].apply(lambda x: x[year_index])
    pop =  spheres['Population'].apply(lambda x: x[year_index])

    if year_index > 5:
        pop_diff = spheres['Population'].apply(lambda x: (x[year_index]- x[year_index-5])/x[year_index-5])
    else:
        pop_diff = spheres['Population'].apply(lambda x: (x[year_index]- x[0])/x[0])
    return [year]*len(prod), prod, pop, pop_diff
spheres['Categorie'] = pd.Series(np.zeros(spheres.index.size), index=spheres.index)
spheres.loc[spheres.index.isin(["91228", "91174"]), "Categorie"] = 2
spheres.loc[spheres.index.isin(["91521", "77296", "91086", "91286", "91182", "77122", "91340", "77445", "77251"]), "Categorie"] = 1<jupyter_output><empty_output><jupyter_text>Évolution temporelle des communes de Grand Paris Sud Description du grapheOn représente sur ce graphe interactif l'évolution de la population et des emplois de la sphère productive des communes de Grand Paris Sud. D'après l'INSEE, la sphère productive est l'ensemble des activités qui produisent des biens majoritairement consommés hors de la zone et des activités de services tournées principalement vers les entreprises correspondantes. Par exemple, une activité d'ingénierie est productive.Cette notion s'oppose à la sphère présentielle qui correspond à l'ensemble des activités produisant des biens consommés dans la zone. Par exemple, une activité de boulangerie est présentielle.Pour chaque commune, la taille du cercle correspond à la population, sa couleur à l'évolution de la population sur les cinq dernières années, et sa position verticale à la taille de la sphère productive (nombre d'emplois).  Utilisation du graphe interactifUtiliser le slider en haut à gauche pour changer l'année, et cliquer sur le cercle d'une commune pour avoir son évolution au cours du temps. Re-cliquer sur un cercle pour repasser à la vue de toutes les communes.En fonction de la taille de votre écran, vous pouvez modifier la hauteur du graphe, en utilisant le slider en haut à droite.<jupyter_code>tt = Tooltip(fields=['name', 'y', 'size'], labels=['Commune', 'Sphère productive', 'Population'])
x_sc = LinearScale(min=1975, max=2025)
y_sc = LogScale(min=prod_min, max=prod_max)
# c_sc = OrdinalColorScale(domain=spheres['Categorie'].unique().tolist(), colors=CATEGORY10[:3])
c_sc = ColorScale(scheme='RdYlGn')
size_sc = LinearScale(min=pop_min, max=pop_max)
c_sc.min = -0.01
c_sc.mid = 0.01
c_sc.max = 0.03
ax_y = Axis(label="Nombre d'employés dans la sphère productive", scale=y_sc, orientation='vertical', side='left', grid_lines='solid')
ax_x = Axis(label='Temps', scale=x_sc, grid_lines='solid')
# Start with the first year's data
year, prod, pop, pop_diff = get_data(initial_year)
wealth_scat = Scatter(x=year, y=prod, color=pop_diff, size=pop,
                      names=spheres['Libellé'], display_names=True,
                      scales={'x': x_sc, 'y': y_sc, 'color': c_sc, 'size': size_sc},
                      default_size=4112, tooltip=tt, animate=True, stroke='Black',
                      hovered_style={'opacity': 0.8}, default_opacities=[0.2])
commune_line = Lines(x=range(initial_year, final_year + 1), y=spheres['Sphère productive'][0], colors=['Gray'],
                       scales={'x': x_sc, 'y': y_sc}, visible=False, animation_duration=0)
time_interval = 500
fig = Figure(marks=[wealth_scat, commune_line], axes=[ax_x, ax_y],
             title='Evolution des communes de Grand Paris Sud', animation_duration=time_interval)
fig.layout.height = '1000px'
fig.layout.width = '950px'
year_slider = IntSlider(min=1975, max=2015, step=1, description='Année', value=initial_year)
height_slider = IntSlider(min=500, max=2000, step=100, description='Hauteur du graphe', value=900, style={'description_width': 'initial'})
def hover_changed(self, change):
    if change['data']['unique_id'] in spheres['Libellé'].values:
        commune_line.y = spheres[spheres['Libellé'] == change['data']['unique_id']]['Sphère productive'].values[0]
        commune_line.visible = True
        wealth_scat.x, wealth_scat.y, wealth_scat.size, wealth_scat.color, wealth_scat.names  = get_data_hover(change['data']['unique_id'])
        wealth_scat.default_opacities = [1]
        fig.title = 'Evolution de la commune de ' + change['data']['unique_id']
    else:
        commune_line.visible = False
        wealth_scat.x, wealth_scat.y, wealth_scat.size, wealth_scat.color  = get_data(year_slider.value)
        wealth_scat.names = spheres['Libellé']
        wealth_scat.default_opacities = [0.2]
        fig.title = 'Evolution des communes de Grand Paris Sud'
        
wealth_scat.on_element_click(hover_changed)
def get_data_hover(libelle):
    prod = spheres[spheres['Libellé'] == libelle]['Sphère productive'].values[0][::5]
    pop =  spheres[spheres['Libellé'] == libelle]['Population'].values[0][::5]
    pop_diff = np.concatenate(([0], np.diff(pop)/pop[:-1]))
    return range(1975,2016,5), prod, pop, pop_diff, range(1975, 2016,5)
def year_changed(change):
    hover_changed(None, {'data':{'unique_id':'placeholder'}})

year_slider.observe(year_changed, 'value')
def height_changed(change):
    fig.layout.height = str(change['new']) + 'px'

height_slider.observe(height_changed, 'value')
play_button = Play(min=1975, max=2015, interval=time_interval)
jslink((play_button, 'value'), (year_slider, 'value'))
VBox([HBox([play_button, year_slider, height_slider]), fig])<jupyter_output><empty_output><jupyter_text>Implantations des entreprises en 2018<jupyter_code># NAF avec sphères
df = pd.read_excel('sphere_NAF_rev2.xls')
df.drop(range(8), inplace = True)
df.columns = ['Code', "Nom de l'activité", 'Code sphere', 'Sphère']
df.set_index('Code', inplace = True)
df.drop('Code sphere', axis=1, inplace = True)
df["Nombre d'installations en 2018"] = pd.Series(np.zeros(df.index.size), index=df.index)
df["Nombre de radiations en 2018"] = pd.Series(np.zeros(df.index.size), index=df.index)
with open('entreprises-immatriculees-en-2018-nettoye.json') as file:  
    list_entreprises = json.load(file)
with open('entreprises-radiees-en-2018-nettoye.json') as file:  
    list_entreprises_radiees = json.load(file)
for entreprise in list_entreprises:
    df.loc[df.index == entreprise['fields']['code_ape'], "Nombre d'installations en 2018"] += 1
for entreprise in list_entreprises_radiees:
    df.loc[df.index == entreprise['fields']['code_ape'], "Nombre de radiations en 2018"] += 1<jupyter_output><empty_output><jupyter_text>Le tableau suivant présente les activités pour lesquelles le plus d'entreprises se sont installées en 2018. On indique le code INSEE de l'activité, son nom, la sphère d'activités (présentielle ou productive) correspondante, et le nombre d'installations et de radiations en 2018.<jupyter_code>df[df["Nombre d'installations en 2018"] > 6].sort_values(by="Nombre d'installations en 2018", ascending=False)
with open('geoflar-communes-IDF.geojson') as file:  
    geo_json_data =  json.load(file)
for commune in geo_json_data['features']:
    commune['id'] = commune['properties']['insee_com']
geo_json_data['features'] = [commune for commune in geo_json_data['features'] if commune['id'] in commune_PGS]
sphere_prod =  dict(zip(spheres.index.tolist(), spheres['Sphère productive 2015'].tolist()))
sphere_pres = dict(zip(spheres.index.tolist(), spheres['Sphère présentielle 2015'].tolist()))
emploi = dict(zip(spheres.index.tolist(), spheres['Emploi total 2015'].tolist()))
choropleth = Choropleth(
    geo_data=geo_json_data,
    choro_data = emploi,
    colormap=linear.YlOrRd_04,
    border_color='black',
    style={'fillOpacity': 0.7, 'dashArray': '5, 5'})
m = Map(center=(48.6068088, 2.5105476379), zoom=12, layout={'height':'800px'})

basemap_layer = basemap_to_tiles(basemaps.OpenStreetMap.Mapnik)
m.add_layer(basemap_layer)
m.add_layer(choropleth)

for entreprise in list_entreprises:
    entreprise['marker'] = Marker(location=entreprise['geometry']['coordinates'][::-1], draggable=False, title=entreprise['fields']['denomination'] + '\n' + entreprise['fields']['libelle_ape'],
      icon = Icon(icon_url='https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png', icon_size=[25, 40], icon_anchor = [12.5, 40]))
    m.add_layer(entreprise['marker'])
        
for entreprise in list_entreprises_radiees:
    entreprise['marker'] = Marker(location=entreprise['geometry']['coordinates'][::-1], draggable=False, title=entreprise['fields']['denomination'] + '\n' + entreprise['fields']['libelle_ape'],
      icon = Icon(icon_url='https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', icon_size=[25, 40], icon_anchor = [12.5, 40]))
    m.add_layer(entreprise['marker'])
secteur_code = {
    'Tous' : range(100), 
    'Agriculture' : range(1, 4), 
    'Industrie' : range(4, 34),
    'Energie / réseaux' : range(34, 39),
    'Construction': range(41, 44),
    'Commerce' : range(45, 48), 
    'Transports' : range(49, 54), 
    'Hotel / Restauration' : range(55, 57), 
    'Services à haute VA' : range(58, 76), 
    'Services publics' : range(77, 89), 
    'Autres' : range(89, 100)
}
list_prod = df.loc[df["Sphère"] == "Productive"].index
list_pres = df.loc[df["Sphère"] == "Présentielle"].index
def change_button(change):
    for l in [list_entreprises, list_entreprises_radiees]:
        for entreprise in l:
            secteur = int(entreprise['fields']['code_ape'][:2])
            ok = (secteur in secteur_code[b2.value])
            if change['new'] == 'Toutes' and ok:
                entreprise['marker'].visible = True
            elif change['new'] == 'Sphère productive':
                if entreprise['fields']['code_ape'] in list_prod and ok:
                    entreprise['marker'].visible = True
                else:
                    entreprise['marker'].visible = False
            elif change['new'] == 'Sphère présentielle':
                if entreprise['fields']['code_ape'] in list_pres and ok:
                    entreprise['marker'].visible = True
                else:
                    entreprise['marker'].visible = False
def change_button2(change):
    for l in [list_entreprises, list_entreprises_radiees]:
        for entreprise in l:
            secteur = int(entreprise['fields']['code_ape'][:2])
            sphere_prod = (entreprise['fields']['code_ape'] in list_prod)
            sphere_pres = not sphere_prod
            ok = (b.value == 'Toutes' or (b.value == 'Sphère productive' and sphere_prod) or (b.value == 'Sphère présentielle' and sphere_pres))
            if secteur in secteur_code[change['new']] and ok:
                entreprise['marker'].visible = True
            else:
                entreprise['marker'].visible = False
b = ToggleButtons(
    options=['Toutes', 'Sphère productive', 'Sphère présentielle'],
    description="Sélectionner la sphère de l'entreprise :",
    disabled=False,
    button_style='', # 'success', 'info', 'warning', 'danger' or ''
    tooltips=['Description of slow', 'Description of regular', 'Description of fast'],
    style={'description_width': 'initial'}
)
b.observe(change_button, names='value')
b2 = ToggleButtons(
    options=['Tous', 'Agriculture', 'Industrie', 'Energie / réseaux', 'Construction', 'Commerce', 'Transports', 'Hotel / Restauration', 'Services à haute VA', 'Services publics', 'Autres'],
    description="Sélectionner le secteur d'activité :",
    disabled=False,
    button_style='', # 'success', 'info', 'warning', 'danger' or ''
    tooltips=['Description of slow', 'Description of regular', 'Description of fast'],
    style={'description_width': 'initial'}
)
b2.observe(change_button2, names='value')<jupyter_output><empty_output><jupyter_text>La carte interactive ci-dessous montre les créations et les destructions d'entreprises sur le territoire de Grand Paris Sud en 2018. Les marqueurs verts correspondent aux créations d'entreprises tandis que les marqueurs rouges correspondent aux destructions d'entreprises.Le fond coloré représente le nombre d'emplois par commune - beaucoup d'emplois dans les communes rouges et peu d'emplois dans les communes jaunes.On peut filtrer les marqueurs en fonction de la sphère de l'entreprise (productive ou présentielle) et du secteur d'activité.<jupyter_code>VBox([b, b2, m])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14145969637299116, 'fraction_numerical': 0.03499968239852633, 'mean_word_length': 4.360572012257405, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, 'https://': 5, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '430879', 'license': 'OML', 'n_tokens_mistral': 5708, 'n_tokens_neox': 5185, 'n_words': 1240, 'path': 'Analyse_data_GPS.ipynb', 'repo_name': 'PierreMarion23/Analyse_GPS', 'size': '15766'}