Outils du BIN
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 à :
- La structure de fichiers
- Les environnements virtuels
- 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
.