Aller au contenu

4. Organiser son projet

Motivation

Dans les chapitres précédents de notre guide méthodologique, nous nous sommes intéressés aux questions de savoir comment coder proprement, comment tester notre code, et comment gérer les différentes versions de celui-ci avec git. On pourrait dire que le guide a été orienté jusqu'ici vers les fichiers de code individuels.
Dans un projet de sciences des données, cependant, on a souvent plusieurs fichiers de codes : des fichiers de code qui extraient des données, d'autres qui les nettoient, d'autres qui produisent des analyses et des visualisations et parfois d'autres qui contiennent des fonctions. C'est sans compter les données qu'on l'on analyse, que l'on nettoie et transforme. Tout ça peut rapidement devenir un casse-tête. À cela s'ajoute parfois une volonté que notre travail soit reproductible par d'autres.
Dans ce guide, nous allons tenter de répondre à la question de savoir comment organiser son projet pour nous éviter des mots de tête.

Plus précisément, nous allons nous intéresser à :

  1. La structure de fichiers
  2. Les environnements virtuels
  3. Les fichiers de configuration

La structure de fichiers

Voici la structure de fichiers que nous recommandons pour les projets qui utilisent R ou Python (qui sont les deux langages de programmation les plus utilisées en science des données). Dans cette section, nous allons nous intéresser aux dossiers code/ et donnees/. L'utilité des autres fichiers sera abordé dans les prochaines sections.

Structure recommandée pour python

├── code/
  │   ├── fonctions/
  │   ├── pipeline/
  │   ├── tests/
  │
├── donnees/
  │   ├── brutes/
  │   ├── en_traitement/
  │   ├── finales/
  │
├── .gitignore
  ├── config.yml
  ├── environnement.yml 
  └── README

Structure recommandée pour R

├── code/
  │   ├── fonctions/
  │   ├── pipeline/
  │   ├── tests/
  │
├── donnees/
  │   ├── brutes/
  │   ├── en_traitement/
  │   ├── finales/
  │
├── renv/
  │
├── .gitignore
  ├── config.yml
  ├── renv.lock 
  └── README

Une première chose que nous recommandons de faire est de mettre le code et les données dans des dossiers séparés. Cela est utile pour au moins deux raisons. La première est qu'on pourra naviguer plus facilement des nos fichiers de code (un projet en science des données générees souvent beaucoup de fichiers de données). La seconde est que le fait d'avoir toutes nos données dans le même dossier nous permettra de dire à git d'ignorer les données d'un seul coup en ajoutant donnees/ dans notre fichier .gitignore (voir le chapitre git – les bonnes pratiques à ce sujet).

Une deuxième chose est la division du dossier code/ en sous-dossiers fonctions/, pipeline/ et tests/. Le dossier fonctions/ contiendra, sans surprise, les fonctions (voir le chapitre Comment coder proprement pour un rafraichissement sur la notion de fonction). Dans le fichier tests/ on trouvera les tests de ces fonctions (pour rappel, nous avons vu dans le chapitre L'importance des tests que les seules choses que nous pouvons tester en bonne et due forme sont les fonctions). Dans le dossier pipeline/ on trouvera tous les fichiers de code qui applique les différentes étapes de notre analyse. Les étapes types d'un projet en science des données sont l'extraction des données, le nettoyage des données, l'analyse puis la visualisation.

Une troisième chose est la division du dossier donnees/ en sous-dossiers brutes/, en_traitement/ et finales/. Dans le sous-dossier brutes/ on trouvera, bien entendu, nos données brutes, dans le sous-dossier en_traitement/ on trouvera les données nettoyées sur lesquels on fera nos analyses, et dans le sous-dossiers finales/ on trouvera les tables et les visualisations qui seront jointes à la publication. Nous croyons qu'il peut être utile de garder séparées les données associées aux différentes étapes de la recherche. Le processus itératif propre aux projets en science des données rend souvent nécessaire de revenir aux données brutes. Les garder dans leur propre dossier nous assure qu'on y aura accès facilement.

Remarque : on pourra très bien subdiviser ces sous-dossiers en d'autres sous-dossiers si on en ressent le besoin.

Les environnements virtuels

Qu'est-ce qu'un environnement virtuel?

Il s’agit d’un interpréteur dédié qui contourne (bypass) l’interpréteur principal de notre machine, ainsi qu’un dossier dédié où seront installées les librairies de notre environnement. Au fond, c’est comme si on avait un nouvel ordinateur sur lequel on venait d’installer l’interpréteur de notre langage de programmation préféré.

À quoi sert un environnement virtuel?

La première fonction des environnements virtuels est de permettre la coexistence de plusieurs projets sur une même machine. En effet, grâce aux environnements virtuels, chaque projet pourra utiliser des versions différentes de l’interpréteur et des librairies. Si on n'utilise pas d'environnement virtuel, il est possible qu'en installant des versions plus récentes d'une librairie, on brise notre code dans un autre projet.
Sur Linux et Mac, le système d’exploitation utilise python, et il est possible qu'une mise à jour de notre interpréteur se fasse sans qu'on en ait connaissance et que cela brise notre code dans certains de nos projets (la mise à jour du système d'exploitation ne touchera pas aux interpréteurs dans nos environnements virtuels).
Finalement, le fait d'avoir un environnement virtuel facilite le partage et la reproduction de notre code. Les outils pour créer des environnements virtuels permettent généralement de recréer le même environnement sur une autre machine.

Comment installer un environnement virtuel?

Pour python

Il existe plusieurs manières de mettre en place des environnements virtuels avec python. L'outil le plus utilisé est Anaconda (ou Miniconda).

Une fois Anaconda ou Miniconda installé, voici les commandes les plus importantes que vous devez exécuter dans votre terminal sur Linux ou Mac. Sur Windows, l'installation d'Anaconda vous donne accès à l'Anaconda Prompt dans lequel vous pouvez exécuter ces mêmes commandes :

Pour créer l’environnement :
conda create -n myenv python=3.9 pandas
explication : conda create crée un nouvel environnement. -n myenv spécifie le nom qu'on donnera à notre environnement (le nom choisi est «myenv» ici). python=3.9 spécifie la version de l'interpréteur python que l'on veut utiliser (si on ne le spécifie pas, la plus récente version sera associée à notre environnement). On peut ensuite écrire une liste de librairies qu'on veut avoir dans notre environnement. Dans ce cas, on a pandas. On aurait pu écrire conda create -n myenv python=3.9 pandas numpy pytorch pour installer aussi numpy et pytorch. Il est évidemment possible d'installer d'autres librairies par la suite.

Pour activiter l'environnement :
conda activate myenv
explications: ici myenv devra évidemment être remplacé par le nom de votre propre environnement

Pour désactiver l'environnement:
conda deactivate

Pour installer une nouvelle librairie une fois l'environnement activé:
conda install numpy=1.23.3
explications : ici on installe la version 1.23.3 de numpy.

Pour exporter l'environnement :
conda env export > environment.yml
explications : comme on l'a dit plus tôt, les environnements virtuels peuvent être recréés sur d'autres machines. Pour ce faire, il faut les exporter. La commande ci-haut générera le fichier ènvironment.yml à partir duquel on pourra créer l'environnement de nouveau sur une autre machine.

Pour créer un environnement à partir d’un fichier yml :
conda env create -f environment.yml

Une question à laquelle on doit répondre est celle de savoir comment intégrer l'environnement virtuel à notre projet une fois qu'il a été créé. Autrement dit, comment coder à l'intérieur de l'environnement virtuel. La réponse à cette question dépend de votre environnement de développement, mais il suffit généralement de spécifier à votre environnement de développement que votre interpréteur python est celui rattaché à un environnement virtuel donné. Voici comment s'y prendre avec Pycharm et VS code.

Pour R

En R, nous vous conseillons d'utiliser la librairie renv.

Installation

Pour installer renv, il suffit de rouler la commande suivante dans RStudio :
intall.packages("renv")

Pour activer l'environnement :
On s'assure que notre working directory soit à la racine de notre projet. On peut faire cela grâce à la commande suivante :
setwd("chemin/vers/notre/projet")
Puis, on lance la commande suivante :
renv::init()
suivi de :
renv::settings$snapshot.type("all")

Pour désactiver l'environnement:
renv::deactivate()

Pour installer une nouvelle librairie une fois l'environnement activé:
Une fois l'environnement activé, on peut installer les librairies comme on le fait habituellement dans R grâce à la commande ìnstall.packages()

Pour exporter l'environnement :
renv::snapshot()
explications: cette fonction crée un fichier renv.lock dans le répertoire du projet. Il contient toutes les informations permettant à renv de recréer l'environnement virtuel. C'est l'équivalent du fichier environment.yml avec Anaconda.

Pour créer un environnement à partir d’un fichier renv.lock :
On s'assure que notre working directory soit à la racine de notre projet et que le fichier renv.lock soit dans ce répertoire puis on lance la commande :
renv::restore()

Les fichiers de configuration

Dans un projet en science des données, il n'est pas rare de voir apparaître des constantes qui sont utilisées dans plusieurs scripts différents, on peut penser à certains chemins d'accès vers nos données ou des variables de configuration qui sont toujours les mêmes. Par exemple, notre analyse pourrait porter sur la période allant de 1950 à 1995 deux valeurs qu'on pourrait assigner aux variables DATE_DEBUT et DATE_FIN. Au lieu de répéter le code qui assigne les valeurs à ces variables dans chaque script qui en fait usage, on devrait centraliser le tout dans un seul fichier. C'est ce à quoi servent les fichiers de configuration.
Il existe plusieurs formats de données qu'on peut utiliser pour des fichiers de configuration. XML et JSON sont deux bons exemples. Nous avons choisi le format YML (prononcé ya-mel) qui est très répandu pour les fichiers de configuration. On peut appeler ce fichier simplement config.yml

Exemple fichier de configuration YML

Voici ce à quoi pourrait ressemble un fichier YML :

chemin_donnees_brutes:"/donnees/brutes/"
chemin_donnees_traitement:"/donnees/en_traitement/"
chemin_donnees_finales:"/donnees/finales/"
chemin_fonctions:"/scripts/fonctions/"
  
DATE_DEBUT:1950
DATE_FIN:1995
  

Importation des données de configuration

En python

Pour importer les données de notre fichier config.yml en python, il suffit d'exécuter les lignes de code suivantes :

from yaml import load, dump, Loader, Dumper

stream = open("config.yml", 'r')
config = load(stream, Loader=Loader)

La variable config sera un dictionnaire qui contient toutes les valeurs de notre fichier de configuration. On pourra donc accéder à DATE_DEBUT en faisant config["DATE_DEBUT"]

En R

Pour R, on peut utiliser la librairie yaml de la manière suivante :

library(yaml)
yaml::read_yaml("config.yml")

On pourra ensuite accéder à nos valeurs de configuration grâce à l'opérateur $. Par exemple, pour avoir accès à DATE_DEBUT on fera config$DATE_DEBUT.