Pourquoi un atelier sur les notebooks ?

  • Le format d’atelier permet de partager des techniques rapidement sans la lourdeur et l’investissement d’une formation

  • QUARTO est polyglotte : R, python, observable javascript, html, css, javascript etc…

  • Les notebooks permettent de mélanger facilement du code (traitements, tableaux, graphes, cartes etc…) et du texte (commentaires de chargé d’études !)

  • Un notebook peut être vu comme le chaînon manquant entre un environnement tableur/traitement de texte et une appli complexe avec du bigdata (appli web, Rshiny, python Dash etc…), mais c’est aussi un moyen simple pour faire de la documentation au format web.

  • Et surtout un notebook est :

    • Dynamique
    • Reproductible
    • Multiformat (article, blog, book, website, dashboard en html mais également possibilité de créer des word, pdf, présentation)
    • Publiable (et responsive design !) notamment chez des hébergeurs gratuit (github pages, quartopub) ou sur un serveur ultrabasique sans aucun paramétrage ni environnement (ex. un simple nginx sur une VM linux)

Proposition d’utiliser R studio

  • Quarto est un outil en ligne de commande (CLI) qui peut être intégré dans différents environnements
  • R studio intègre quarto avec une interface userfriendly
  • Au préalable, penser à installer R !
  • Aucun paramétrage à faire…

Télécharger R et R studio

Astuce

Pour l’utiliser avec Visual Studio Code

  • Télécharger R

  • Pour QUARTO, deux possibilités :

    • Vous avez installé R studio : rajouter simplement le chemin suivant dans les variables d’environnement C:\Program Files\RStudio\resources\app\bin\quarto\bin (à adapter)

    • Vous ne comptez pas installer R studio : télécharger et installer quarto

  • Enfin, dans VSC téléchargez les extensions R et QUARTO

Atelier : créer son premier notebook

Au programme :

  • Quelques exemples aboutis
  • L’interface visuelle de R studio
  • Le site ressource Quarto
  • Les bases du markdown et quelques possibilités avancées
  • Mise en forme (theme, custom css)
  • Premiers chunks de code (lire une donnée, faire un tableau téléchargeable, un graphe, une carte)

Selon le temps et vos envies :

  • Export en html, pdf, docx
  • Intégration continue
  • Reveal, dashboard, website, book ou la puissance du yaml pour composer à façon
  • Possibilités de diffusion (standalone, gitpage, quartopublish etc…)
  • Exemples avancés de chunk en R, en python, en observable javascript (ojs)
  • Interactivité en ObservableJavaScript (ojs) ou R shiny
  • Se connecter à postgres
  • Démos de sites complets

Le site ressource QUARTO

Le site ressource Quarto est très complet avec plusieurs approches possible pour l’apprentissage (get starded, guide et reference). C’est un outil de travail à ingurgiter en fonction des besoins. Pour les plus curieux, le forum de discussion permet également d’interagir avec d’autres utilisateurs et parfois même l’équipe de développement.

Création du projet et édition en mode visual

Créer un nouveau projet

R studio propose des boîtes de dialogue pour créer un nouveau projet quarto :
- file\new project

Créer un nouveau projet (suite)

Pour commencer, un Quarto project permet de se familiariser avec les principes de bases.

L’interface R studio

L’interface R studio (suite)

Interface Rstudio

3 fichiers ont été créé :

- _quarto.yml : c’est un fichier de configuration, il va s’appliquer à tous les documents quarto présents dans le répertoire, il est surtout important pour les websites, book, blogs. Le format YAML est un standard plutôt lisible pour des fichiers de configuration notamment avec une indentation pour les arboresences.

- exercice_1.qmd : c’est le fichier QuartoMarkDown, c’est là que tout va se passer et il contient déjà un en-tête en yaml, du texte, un bloc de code.

  • exercice_1.Rproj : c’est le fichier de sauvegarde du projet Rstudio
Un bouton renderpermet de visualiser le rendu (“avec une option render on save”). Les plus aguerris préfereront taper dans le terminal : quarto preview exercice_1.qmd pour prévisualiser et quarto render exercice_1.qmd pour faire un rendu complet.
Le terminal permet de taper directement des lignes de commande, les lignes de commandes de Quarto offrent beaucoup de possibilités mais on peut s’en passer pour débuter.
Rstudio propose un onglet environnement très pratique pour visualiser les données ou connexions pour les codes en R
Deux modes d’édition sont possibles : Source et Visual. Le mode Visual ressemble à un petit traitement de texte et permet de faire des mises en pages sans connaître le markdown. C’est un bon point de départ mais les possibilités de mises en page sont bien plus grandes en mode Source que celles proposées dans ce mode Visual.

Les bases du markdown

Edition en mode visual

Le mode visuel permet de gérer les titres, les puces, les numérotations, gras/italique, tableaux, images, hyperliens et propose quelques mises en forme couramment utilisées mais moins classique comme les blockquote, lineblock, callout, tabset, emoji.

Un raccourci bien pratique

taper / pour faire apparaître toutes les possibilités et vous éviter d’aller dans le menu !

Session de travail

Copier coller des images, oui c’est possible !

En mode visual, vous pouvez copier coller des images à la volée, elles s’enregistreront automatiquement dans un répertoire images (qui se crééra automatiquement si besoin)

le callout Collapsable

Avec la propriété collapse = true, il est possible de rendre le callout collapsable, très pratique pour les encarts en savoir plus…

::: {.callout-tip collapse="true"} 
blabla
:::

et le HTML ?

Et oui c’est possible aussi, si les possibilités du markdown ne vous suffisent pas… écrivez directement en html !

Plusieurs manières de faire des colonnes…

mais la plus simple est d’encapsuler son text dans des blocs de colonnes et de régler la largeur relative des colonnes.

::: columns

::: {.column width="50%"}
blabla
:::

::: {.column width="50%"}
blabla
:::

:::

des icons prêt à l’emploi

Quarto intègre bootstrap et bsicons, pour mettre un icon, on peut écrire

<i class="bi bi-bug"></i>

Le résultat sera un joli icon :

Mise en forme

Theme ou css maison ?

Une multitude de themes

Aperçu des mises en forme prêtes à l’emploi
Dans le fichier _quarto.yaml, rajouter le code suivant pour préciser le theme choisi et expérimentez avec les mises en forme possibles (themes) et essayer en plusieurs (exemple : darkly, quartz, vapor )

project:
  title: "exercice_1"

format:
  html:
    theme: united

Des mises en forme “maison” (exemple CEREMA).

Une mise en forme personnalisée peut s’appuyer sur un theme existant et ne modifier que le nécessaire, exemple avec une ossature de site web :

project:
  title: "exercice_1"

format:
  html:
    theme: [default, custom.scss]

Le fichier custom.scss déposé à la racine du projet contient uniquement les personnalisations nécessaire. Un custom.scss aux couleurs du cerema est déjà prêt à l’emploi.
Cette ossature de site web est dispo ici dans le zip des ressources téléchargeables

Mes premiers CHUNKS de code

On va essayer de reproduire ce notebook R (avec widget HTML)

🤯 ne paniquez pas…

Les options d’exécution

De base, lorsque vous allez mettre vos bouts de code :

  • le code sera affiché (output: true)
  • le code s’exécutera (eval: true)
  • les messages d’erreurs et d’avertissements seront affichés (warning: true)
  • le résultat de votre code s’affichera (ex. un graphe, une carte) (output: true)

Deux options s’offrent à vous :

  • Indiquer dans chaque bloc de code le comportement que vous souhaitez avec true et false
  • Indiquer dans l’en-tête YAML du document comment vous gérer l’ensemble du document, exemple pour l’atelier
---
title: "Atelier Quarto - Exercice 1"
subtitle: "R avec WidgetHTML : tableau, graphe, carte, inline code"
toc: true
format:
  html:
    code-fold: true # les blocs de code seront repliés, NB : on n'est pas obligé de mettre de code, on peut juste afficher les résultats si l'on veut
    code-summary: "Afficher le code" # message pour le symbole de flèche permettant de dérouler le code
execute: 
  warning: false # ne pas afficher les messages d'avertissement
---

… il y a beaucoup d’autres options plus subtiles dans la doc Quarto sur les options d’exécution

Etape 1 : quelques librairies

Si ce n’est pas déjà fait, installez les packages ci-dessous, R propose un menu dédié à la recherche et à l’installation des packages :

Utiliser le bouton pour ajouter un chunk de code (en R, python ou ojs) : Et voilà, on va commencer à coder ⌨️ dans des petits chunks.

library(dplyr) # package pour manipuler les données
library(ggplot2) # package pour les graphes
library(plotly) # package pour rendre un ggplot interactif
library(DT) # package pour afficher les résultats dans des tableaux HTML
library(sf) # package géographique de R
library(leaflet) # package pour les webmap

Etre admin ou ne pas être…

Une petite ligne de commande préalable pour installer Jupyter. Attention ! Il faut faire un clic droit ouvrir l'invite de commande en tant qu'administrateur sinon vous aurez surement une erreur liés aux droits d’écriture…

Et donc pour installer jupyter : py -m pip install jupyter
Puis les librairies nécessaires
pip install plotly
pip install geopandas
pip install pandas
pip install mapclassify
pip install folium

Ajouter un chunk python et commencer à coder :

import geopandas as gpd
import pandas as pd
import plotly.express as px
from IPython.display import display, HTML
import folium
from folium.features import GeoJsonTooltip
import { aq, op } from '@uwdata/arquero' // le dplyr ou pandas du javascript
bertin = require("bertin") // le ggplot de la carto en javascript
import {view} from "@neocartocnrs/geoverview"

Etape 2 : Lecture et manipulation de la donnée

Télécharger la donnée communes_mrn.geojson

# Fonction pour lire un geojson
communes_mrn <- st_read("data/communes_mrn.geojson")

# Utilisation du vocabulaire de dplyr pour sélectionner quelques colonnes 
communes_mrn_qqs_colonnes <- communes_mrn %>% 
  st_drop_geometry() %>% 
  select(nom, population, surface_ha)
# Fonction pour lire un geojson
communes_mrn = gpd.read_file("data/communes_mrn.geojson")

# Utilisation du vocabulaire de pandas pour sélectionner quelques colonnes 
communes_mrn_qqs_colonnes = communes_mrn.drop(columns='geometry')[['nom', 'population', 'surface_ha']]
communes_mrn = FileAttachment("data/communes_mrn_crs4326.geojson").json()
// on va manipuler la donnée differement en javascript... cf prochain chunk !
// On commence ici par créer le tableau de donnée correspondant aux propriétés du geojson avec une fonction bien pratique de la librairie bertin
communes_mrn_table = bertin.properties.table(communes_mrn)

Etape 3 : Affichage du tableau de données

# Affichage du tableau de donnée
datatable(communes_mrn_qqs_colonnes)
display(HTML(communes_mrn_qqs_colonnes.to_html()))
<IPython.core.display.HTML object>
print(communes_mrn_qqs_colonnes)
                              nom  population  surface_ha
0                          Elbeuf       16087        1632
1                       Yainville        1037         331
2                      Hénouville        1366        1069
3                        Canteleu       13807        1761
4        Saint-Étienne-du-Rouvray       28331        1825
..                            ...         ...         ...
66  Sainte-Marguerite-sur-Duclair        2027         726
67      La Neuville-Chant-d'Oisel        2378        2183
68                         Oissel       12266        2219
69                        Duclair        4010        1002
70   Saint-Martin-de-Boscherville        1536        1291

[71 rows x 3 columns]
Inputs.table( 
  communes_mrn_table,
  {
    height: 800,
    columns:["nom", "population"] // choix des colonnes à afficher
  }
)

Prenons un peu de recul !

Ecrire du code peut paraître un peu fastidieux au début… mais ces quelques lignes sont beaucoup plus logiques que :

  • Se demander avec quoi on ouvre un geojson…

  • Se demander comment convertir un geojson en excel

  • Ouvrir dans excel le fichier, sélectionner les colonnes à supprimer, cliquer sur supprimer les colonnes en se demandant si il faudrait pas faire une copie au cas où

  • Faire un copier coller de ce tableau dans une page A4 et se demander comment la mettre en page

  • Se rendre compte vous avez une donnée à corriger… et tout recommencer

L’environnement des notebooks, en plus d’être libre et gratuit, vous permet de gérer absolument tous les formats (xls, csv, json, geojson, gpkg, shp, postgres, parquet etc…) dans un même environnement. Une fois une technique apprise, un simple copier coller vous permet de réinvestir vos connaissances.

Et si vous modifiez la donnée (mise à jour annuelle par exemple)… il suffit de relancer votre notebook pour que tout se mette à jour 🤩.

Etape 4 : Un premier graphe

# Utilisation de la librairie ggplot pour faire un graphe 
g <- ggplot(communes_mrn, aes(x = reorder(nom, population), y = population)) +
  geom_bar(stat = "identity", fill = "purple", color = "white") + # identity ou count pour les stats
  coord_flip() +
  labs(
    x = "Région",
    y = "Communes"
  ) + 
  theme_minimal()

# transformation en un graphe interactif
ggplotly(g,width = 600, height = 1200)
fig = px.bar(
    communes_mrn.sort_values(by='population', ascending=True),
    y='nom',  # Utiliser y pour les noms des communes
    x='population',  # Utiliser x pour les populations
    title='Population des Communes de la MRN',
    labels={'nom': 'Commune', 'population': 'Population'},
    text='population',
    orientation='h',  # Graphique en barres horizontales
    height=1200
)

fig
// La librairie plot est intégrée directement
Plot.plot({
  marginLeft: 180,
  x: {axis: "top", grid: true},
  marks: [
    Plot.barX(
      communes_mrn.features.map(d => d.properties), {
        x: "population", 
        y: "nom", 
        tip: "xy",
        sort: {y: "x", reverse: true}
    })
  ]
  
})

La grammaire de la Dataviz

En mal d’inspiration ? Besoin d’idées ?

R et l’extension esquisse

Il est possible de faire des graphes avec des glisser déposer et de générer le code correspondant… plus d’excuse pour ne pas se mettre à la dataviz ! Comment installer et utiliser Esquisse

Etape 5 : Une première carte pour visualiser les géométries

# Au préalable, il est nécessaire de reprojeter la couche dans CRS attendu par leaflet
# En général les geojson sont directement en 4326 mais ayez en tête que si vous ne voyez pas vos données, c'est surement un problème de projection !
communes_mrn <- st_transform(communes_mrn, crs = 4326)

# Ajout d'une carte leaflet
leaflet(communes_mrn) %>% # on indique la donné
  addTiles() %>% # on charge le fond de plan de base (osm)
  addPolygons()  # on ajoute les polygones de la donnée
# Ajout d'une carte leaflet
communes_mrn.explore()
Make this Notebook Trusted to load map: File -> Trust Notebook
// la fonction pratique chargée dans les appels de librairie
view(communes_mrn)

Etape 6 : Carte en aplat de couleur

# Calcul de la densité de population avec les fonctions de R
communes_mrn$densite_population = round( communes_mrn$population / communes_mrn$surface_ha )

# Création d'une palette de couleur
palette2 <- colorBin(palette = "Blues", domain = communes_mrn$densite_population, bins = 10)

# Le code ci-dessous est un copier collé de la documentation avec quelques adaptations, cela peut sembler fastidieux mais une fois la logique intégrée, faire des cartes prend le temps de changer le nom de l'indicateur...
leaflet(communes_mrn) %>%
  addTiles() %>% 
  addPolygons(
    fillColor = ~palette2(densite_population),
    weight = 1,
    color = "black",
    fillOpacity = 0.7,
    highlightOptions = highlightOptions(
      weight = 3,
      color = "#666",
      fillOpacity = 0.9,
      bringToFront = TRUE
    ),
    label = ~paste("Commune:", nom, " Densité:", densite_population," habitants par hectare")
  ) %>%
  addLegend(
    pal = palette2,
    values = ~densite_population,
    opacity = 0.7,
    title = "Population",
    position = "bottomright"
  )
communes_mrn = communes_mrn.to_crs(epsg=4326)

# Créer une carte centrée sur le centroïde
m = folium.Map()

# se caler sur les limites de la couche
bbox = communes_mrn.total_bounds
minx, miny, maxx, maxy = bbox
bounds = [[miny, minx], [maxy, maxx]]
m.fit_bounds(bounds)



# Choroplèthe
chloropeth = folium.Choropleth(
    geo_data=communes_mrn,
    data=communes_mrn,
    columns=["nom", "population"],
    key_on="feature.properties.nom",
    fill_color="Reds",
    bins=10,
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="Population / commune",
    highlight=True,
)

# Define the tooltips
tooltip = GeoJsonTooltip(
    fields=['nom', 'population', "insee_com"],
    aliases=['Commune: ', 'Population: ', "Code INSEE:"],
    localize=True,
    sticky=False,
    smooth_factor=0,
    labels=True,
    style="""
        background-color: #F0EFEF;
        border: 2px solid black;
        border-radius: 3px;
        box-shadow: 3px;
        font-size: 12px;
    """,
    max_width=750,
)

chloropeth.geojson.add_child(tooltip)
<folium.features.GeoJson object at 0x00000234CE963F50>
chloropeth.add_to(m)
<folium.features.Choropleth object at 0x00000234E067EC90>
# Ajouter un contrôle de couches
folium.LayerControl().add_to(m)
<folium.map.LayerControl object at 0x00000234E06B4770>
# Afficher la carte
m
Make this Notebook Trusted to load map: File -> Trust Notebook
// La librairie bertin est développé par un géographe français et très bien documentée
bertin.draw({
  params: { projection:"Mercator", margin: 50},
  layers: [
    {
      type: "layer",
      geojson: communes_mrn,
      stroke:"black",
      fill: {
        type: "choro",
        values: "population",
        nbreaks: 5,
        method: "jenks",
        colors: "Reds",
        leg_round: -1,
        leg_title: `Population`,
        leg_x: 10,
        leg_y: 10
      },
      fillOpacity: 0.5,
      tooltip: ["$nom","$population"]
    },
    {
      type:"tiles",
      style:"openstreetmap"
    },
  ]
})

Etape 7 : Intégrer des résultats dans une rédaction (Inline code)

pop_rouen <- communes_mrn  %>% 
  st_drop_geometry() %>% 
  filter(insee_com=='76540')  %>% 
  select(population) %>% 
  format(big.mark = " ")

  print(pop_rouen)
  population
1    114 187

Rouen compte 114 187 habitants.
Dans cette phrase, le nombre d’habitants est issus directement du code grace à la syntaxe inline code.

# Filtre
pop_rouen_df = communes_mrn[communes_mrn['insee_com'] == '76540'][['population']]

# et pour passer d'un dataframe à une simple valeur
pop_rouen_value = f"{pop_rouen_df.iloc[0, 0]:,}".replace(',', ' ')
print(pop_rouen_value)
114 187

Rouen compte {python} pop_rouen_value habitants.
Dans cette phrase, le nombre d’habitants est issus directement du code grace à la syntaxe inline code.

pop_rouen = bertin.properties.table(communes_mrn)
    .filter(commune => commune.insee_com === '76540')  // Filtrer par code_insee
    .map(commune => commune.population); // récupérer la propriété population

Rouen compte habitants.
Dans cette phrase, le nombre d’habitants est issus directement du code grace à la syntaxe inline code.

Rendu et diffusion

Rendu de votre projet

  • Le bouton render de Rstudio est un raccourci qui écrit pour vous dans le terminal quarto preview quarto_presentation_reveal.qmd --to revealjs --presentation --no-watch-inputs --no-browse selon les options sélectionnées
  • Pour une prévisualisation qui se met à jour à chaque modification, tapez simplement quarto preview (+ préciser le nom du fichier si besoin) dans le terminal et hop votre projet va s’afficher et se mettre à jour à chaque sauvegarde
  • Pour exporter tout votre projet tapez simplement quarto render (préciser le nom du fichier si besoin) dans le terminal et hop votre projet va être tricoté et prêt à être publié
  • Nous avons travaillé en html (format par défaut aujourd’hui) mais il est possible de faire des sorties en docx ou pdf (attention : il faut alors utiliser des librairies comme ggplot et non des widget html !)

Diffusion sur le web

Il y a plusieurs possibilités pour diffuser vos résultats sur le web :

  • Si vous avez accès un ftp, vous déposer simplement vos fichiers. La DTERNC a maintenant un serveur exposé internet pour diffuser vos notebooks !
  • Si vos données sont publiques, des offres gratuites sont également disponibles
    • Quartopub
    • Github pages
  • Attention, si vos données sont sensibles ou non diffusables grand public, il faudra trouver une autre approche (exemple empaqueter votre site dans un shiny avec mot de passe ou utiliser htpassword sur le serveur de la DTERNC par exemple)

Astuce

Et si vous n’avez pas mis de fonctionnalités avancées, votre html sera autonome lisible tel quel (mail, clef usb, simple fichier sur votre disque dur) !

Quarto Pub

Vos données sont publiques ? Votre projet fait moins de 100 Mo ? Quarto Pub vous permet de diffuser sur le web !

  • Créer vous un compte sur Quarto Pub
  • Connecter vous à votre espace et laisser la page ouverte
  • Taper quarto publish quarto-pub dans le terminal
  • Répondez aux questions posées dans le terminal

Et maintenant, sur la page dans votre compte Quarto Pub vous voyez votre projet avec une adresse web pour le diffuser💓.

GITLAB en CI/CD

La DDTM76 propose sur son dépôt Gitlab un template de repo pour pouvoir créer une gitlabpages et la publier (nécessité d’avoir un compte cerbérisé et les droits sur l’instance ministérielle) :
EZ Quarto GitPage

Les principes essentiels :

  • Dans Gitlab : “Settings” > “CI/CD” > “Runners”, activer la coche “Enable instance runners for this project”.
  • Préciser la procédure dans un .gitlab-ci.yml en cohérence avec _quarto.yaml

Les ressources : exemples en ligne et codes sources téléchargeables

Quelques exemples

Téléchargez un .zip de toutes les ressources

Conclusion

Les notebooks offrent de nombreuses possibilités et la courbe de progression est assez douce si l’on commence par faire de simples articles.

Ils sont particulièrement adaptés pour :

  • la documentation

  • les articles simples de type scientifiques (c’est le standard pour les publications web)

  • les rendus sous forme de sites web ou webbook

  • le travail en équipe aux profils variés (exemple : différentes personnes pour rédiger le contexte et les enjeux, préparer les données sous postgres, faire un traitement python, mettre en place une dataviz, commenter les résultats)

  • les proofs of concept (POC) de dataviz avant de passer sur une archi plus lourde

  • … et les diaporamas comme celui ci, qui utilise le moteur reveal.js