Environnements reproductibles pour la science des données avec {rix}

Bruno Rodrigues

Intro : Qui suis-je

Bruno Rodrigues, responsable du département de statistique au Ministère de la Recherche et de l’Enseignement supérieur au Luxembourg

Intro : Contenu

Diapositives disponibles en ligne :

https://b-rodrigues.github.io/repro_rrr

Code disponible ici :

https://github.com/b-rodrigues/repro_rrr

Ce dont je vais parler

Le puzzle que vous connaissez:

Ce dont je vais parler

Le puzzle avec Nix:

Solutions disponibles pour R

  • {renv} ou {groundhog}: simple à utiliser, mais :
    • Ne sauvegarde pas la version de R
    • L’installation d’anciens packages peut échouer (dépendances système)
  • Docker permet d’aller plus loin :
    • Gère R et les dépendances système
    • Conteneurs exécutables n’importe où
  • Mais :
    • N’est en soi pas reproductible

Le gestionnaire de paquets Nix (1/2)

Gestionnaire de paquets : outil permettant d’installer et de gérer des paquets

Paquet : tout logiciel (pas uniquement les packages R)

Un gestionnaire de paquets populaire :

Google Play Store

Le gestionnaire de paquets Nix (2/2)

  • Pour garantir la reproductibilité : R, les packages R et autres dépendances doivent être gérés explicitement
  • Nix est un gestionnaire de paquets réellement centré sur les builds reproductibles
  • Nix gère tout à l’aide d’un seul fichier texte (appelé une expression Nix) !
  • Ces expressions produisent toujours exactement le même résultat

rix : environnements de développement reproductibles avec Nix (1/5)

  • {rix} (site web) simplifie l’écriture d’expressions Nix !
  • Il suffit d’utiliser la fonction rix() fournie :
library(rix)

rix(date = "2025-06-13",
    r_pkgs = c("dplyr", "ggplot2"),
    system_pkgs = NULL,
    git_pkgs = NULL,
    tex_pkgs = NULL,
    ide = "code",
    project_path = ".")

rix : environnements de développement reproductibles avec Nix (2/5)

  • Les fichiers renv.lock peuvent aussi servir de point de départ :
library(rix)

renv2nix(
  renv_lock_path = "path/to/original/renv_project/renv.lock",
  project_path = "path/to/rix_project",
  override_r_ver = "4.4.1" # <- optionnel
)

rix : environnements de développement reproductibles avec Nix (3/5)

  • Lister la version de R et les packages nécessaires
  • En option :
    • packages système, packages depuis GitHub, ou packages LaTeX
    • un IDE (Rstudio, Radian, VS Code ou “autre”)
    • une version de Python et paquets Python à inclure
    • une version de Julia et paquets Julia à inclure

rix : environnements de développement reproductibles avec Nix (4/5)

  • rix::rix() génère un fichier default.nix
  • Construire les expressions avec nix-build (en terminal) ou rix::nix_build() depuis R
  • Accéder à l’environnement de développement avec nix-shell
  • Les expressions peuvent être générées même sans Nix installé (avec quelques limitations)

rix : environnements de développement reproductibles avec Nix (5/5)

  • Peut installer des versions spécifiques de packages (écrire "dplyr@1.0.0")
  • Peut installer des packages hébergés sur Github
  • De nombreuses vignettes pour démarrer ! Voir ici

Démonstration

  • Les bases : scripts/nix_expressions/01_rix_intro/
  • Vs Code/Positron natifs sur Windows: scripts/nix_expressions/02_native_vscode_example/
  • Nix et {targets}: scripts/nix_expressions/03_nix_targets_pipeline
  • Nix et Docker: scripts/nix_expressions/04_docker/
  • Nix et {shiny}: scripts/nix_expressions/05_shiny
  • GitHub Actions: voir ici

Pipelines polyglottes avec {rixpress}

  • {rixpress} permet d’enchaîner des étapes de traitement en R et Python
  • Utilise {rix} pour créer un environnement reproductible (via Nix) d’exécution de la pipeline
  • Chaque étape de pipeline est une dérivation Nix
  • Transfert de données : automatique via reticulate ou format universel (JSON)

Un exemple de pipeline mixte

list(
  rxp_py_file(…),    # Lire un CSV avec Python
  rxp_py(…),         # Filtrer avec Polars
  rxp_py2r(…),       # Transfert Python → R
  rxp_r(…),          # Transformation en R
  rxp_r2py(…),       # Transfert R → Python
  rxp_py(…),         # Autre étape Python
  rxp_py2r(…),       # Retour vers R
  rxp_r(…)           # Étape finale
) |> rixpress()
  • Chaque étape est nommée, typée (py, r, r2py, etc.)
  • Possibilité d’ajouter des fichiers (functions.R, images…)

Transfert avec JSON (ou autre format universel)

  • Avantage : évite d’utiliser reticulate
  • Ajouter une fonction de sérialisation Python :
def serialize_to_json(pl_df, path):
    with open(path, 'w') as f:
        f.write(pl_df.write_json())
  • Et côté R :
rxp_r(
  name = "x",
  expr = my_fun(data),
  unserialize_function = "jsonlite::fromJSON"
)

Génération de documents (Quarto ou Rmd)

  • Intégration facile de la sortie du pipeline dans un .qmd :
```r
rixpress::rxp_read("mtcars_head")
```
  • Tous les objets créés peuvent être chargés dynamiquement dans le document
  • Possibilité de transmettre des fichiers supplémentaires (content.qmd, images…)

Démo interactive

Voir scripts/rixpress_demo

Pour en savoir plus:

Fin

Contactez-moi si vous avez des questions :

Merci !