Importer des données

Avant de rentrer dans le vif du sujet, je vais vous demander, si vous ne l’avez pas déjà fait, de créer un répertoire de travail dédié à cette formation. Par convention entre nous, nous allons considérer que l’adresse de votre répertoire de travail est :

C:\…\R

Une fois votre répertoire créé, sauvegardez-y les fichiers PopReg.csv, test1.csv, test2.csv et test3.csv (Cliquez sur le lien puis sélectionnez File/Download.)

C’est fait ? Poursuivons…

R est capable de se connecter à nombre considérable de sources de données mais cela implique souvent que vous disposiez de fonctions relativement complexes à coder (la plupart desquelles vous seront fournies par des packages).

Nous allons donc commencer par là où nous avons tous commencé : importer des fichiers .csv (pour Comma-Separated Values).

Ouvrez un nouveau script, faites un peu de ménage si nécessaire et créez l’objet suivant :

mydir <- "C:/…/R"

Notez que j’ai remplacé les antislashs de Windows par des slashs et n’oubliez pas les doubles guillemets.

Nous allons travailler avec le fichier PopReg.csv ce qui implique que nous indiquions à R où il se trouve. Pour ce faire, nous allons créer une vecteur character qui décrit le chemin d’accès à ce fichier :

> paste(mydir, "PopReg.csv", sep = "/")
[1] "C:/…/R/PopReg.csv"

Ou, puisque la fonction existe :

> file.path(mydir, "PopReg.csv")
[1] "C:/…/R/PopReg.csv"

Nous allons passer ce chemin d’accès comme premier argument de la fonction read.csv qui est une variante de la très vénérable fonction read.table.

Si vous jetez un coup d’œil à l’aide (?read.table n'est-ce-pas ?), vous remarquerez que le nombre d’arguments possibles est assez important. La raison en est fort simple : read.table et ses variantes ont été conçues pour s’adapter à (presque) tous les formats de fichiers possibles et vous verrez bientôt que ce n’est pas un luxe inutile.

Allons-y :

PopReg <- read.csv(file.path(mydir, "PopReg.csv"))

Sauf erreur de votre part :

> class(PopReg)
[1] "data.frame"

Offrez-vous un petit fix.

Ce fichier, réalisé par mes soins, contient des données (plus ou moins exactes) sur la population (Pop) des différentes régions françaises (Region) de métropole (Type = M) et d’outre-mer (Type = OM) de 2000 à 2011 (Annee).

Exécutez :

> summary(PopReg)
             Region    Type         Annee           Pop          
 Alsace         : 12   M :264   Min.   :2000   Min.   :  205954  
 Aquitaine      : 12   OM: 48   1st Qu.:2003   1st Qu.: 1173440  
 Auvergne       : 12            Median :2006   Median : 1839393  
 Basse-Normandie: 12            Mean   :2006   Mean   : 2481410  
 Bourgogne      : 12            3rd Qu.:2008   3rd Qu.: 3175704  
 Bretagne       : 12            Max.   :2011   Max.   :11852851  
 (Other)        :240

La fonction summary est une fonction générique qui a un comportement différent pour chaque classe d’objet. En l’occurrence, puisque PopReg est un dataframe, elle nous retourne une table de contingence pour les colonnes de texte et quelques informations sur la distribution des données numériques (ce qui implique accessoirement que R a automatiquement reconnu la nature des données de chaque colonne de mon fichier).

Malheureusement, les choses ne sont pas toujours aussi simples : vous allez très fréquemment être confrontés à des fichiers .csv plus ou moins faciles à importer.

Test #1

Le fichier test1.csv est une version courte de PopReg.csv. Nous allons essayer de le lire de la même façon.

mydir <- "C:/…/R"
test1 <- read.csv(file.path(mydir, "test1.csv"))

Ça fonctionne :

> test1 <- read.csv(file.path(mydir, "test1.csv"))
> test1
                     Region Type Annee      Pop
1                    Alsace    M  2011  1852325
2                    Alsace    M  2010  1845687
3                 Aquitaine    M  2011  3254233
4                 Aquitaine    M  2010  3232352
5                  Auvergne    M  2011  1350682

Maintenant, essayons avec read.table :

> test1 <- read.table(file.path(mydir, "test1.csv"))
> test1
                                    V1
1                Region,Type,Annee,Pop
2                Alsace,M,2011,1852325
3                Alsace,M,2010,1845687
4             Aquitaine,M,2011,3254233
5             Aquitaine,M,2010,3232352

Gruik ! read.table a du mal à lire ce fichier, nous allons devoir l’aider un peu en lui signalant que (i) les données de test1.csv sont séparées par des virgules et (ii) la première ligne contient les noms de colonnes.

> test1 <- read.table(file.path(mydir, "test1.csv"),  sep = ",", h = TRUE)
> test1
                     Region Type Annee      Pop
1                    Alsace    M  2011  1852325
2                    Alsace    M  2010  1845687
3                 Aquitaine    M  2011  3254233
4                 Aquitaine    M  2010  3232352
5                  Auvergne    M  2011  1350682

La fonction read.csv est cas spécial de read.table spécialement conçu pour lire des fichiers .csv. En fait, read.csv appelle read.table avec des arguments adaptés aux fichiers .csv.

Test #2

Prenons maintenant test2.csv :

> test2 <- read.csv(file.path(mydir, "test2.csv"))
> test2
              Fichier.conçu.par.Guillaume.Nicoulaud
Region;Type;Annee;Pop                            NA
Alsace;M;2011;18523                              25
Alsace;M;2010;18456                              87

GRUIK !

Le concepteur de ce fichier a eu l’idée stupide de signer son crime sur la première ligne. Nous allons avoir recours à l’argument skip qui permet d’ignorer les premières lignes (ici la première) :

> test2 <- read.csv(file.path(mydir, "test2.csv"), skip = 1)
> test2
                              Region.Type.Annee.Pop
Alsace;M;2011;18523                              25
Alsace;M;2010;18456                              87
Aquitaine;M;2011;32542                           33

Manifestement, nous allons devoir préciser que les points-virgules sont des séparateurs :

> test2 <- read.csv(file.path(mydir, "test2.csv"), skip = 1, sep = ";")
> test2
                     Region Type Annee       Pop
1                    Alsace    M  2011  18523,25
2                    Alsace    M  2010  18456,87
3                 Aquitaine    M  2011  32542,33

Voilà qui est mieux n’est-ce-pas ? Sauf que :

> class(test2$Pop)
[1] "factor"

Comme le concepteur de ce fichier — maudit soit-il ! — a cru bon d’utiliser des virgules comme séparateur décimal, R à interprété la colonne Pop comme du texte (et l'a transformée en factor).

> test2 <- read.csv(file.path(mydir, "test2.csv"), skip = 1, sep = ";",
      dec = ",")
> test2
                     Region Type Annee       Pop
1                    Alsace    M  2011  18523.25
2                    Alsace    M  2010  18456.87
3                 Aquitaine    M  2011  32542.33

Nous y voilà.

Test #3

C’est avec test3.csv que nous allons vraiment rire. Je tiens à préciser que j’ai trouvé ce fichier sur un site tout à fait sérieux (que je ne nommerai pas par charité) et que je n’ai fait que réduire la quantité de données à l’intérieur.

Ouvrez-le avec un éditeur de texte et constatez l’ampleur du massacre.

Eh bien même avec ça, nous allons nous en sortir. Démonstration :

1 — On utilise scan avec what = "character" et sep = "\n" pour scanner le fichier comme si c’était du texte séparé par des retours à la ligne :

tmp <- scan(file.path(mydir, "test3.csv"),
      what = "character", sep = "\n")

On ouvre une textConnection, on le lit ça avec read.csv en précisant qu’il n’y a pas de noms de colonnes et on n’oublie pas de fermer la connexion :

con <- textConnection(tmp[6:36])
test3 <- read.csv(con, h = FALSE)
close(con)

On repère la position des valeurs non-manquantes de la deuxième colonne avec un vecteur logique ix :

tmp <- as.character(test3[[2]])
ix <- tmp != "."

On utilise ix pour indexer la deuxième colonne ; ce qui nous permet de la convertir au format numérique :

Valeurs <- as.numeric(tmp[ix])

On s’assure que les dates sont des Date et on en profite pour ne sélectionner que celles qui nous intéressent avec ix :

Dates <- as.Date(test3[[1]])[ix]

On construit un dataframe tout neuf :

test3 <- data.frame(Dates, Valeurs)

Ce qui nous donne :

> test3
        Dates Valeurs
1  1998-01-02  29.886
2  1998-01-05  29.877
3  1998-01-06  29.866

Comme dirait le général :

Avec textConnection, vous pouvez aussi faire ce genre de choses :

"Year,Value
2010,158
2011,160
2012,157
2013,155" -> raw

con <- textConnection(raw)
Dta <- read.csv(con)
close(con)

Ce qui vous donne :

> Dta
  Year Value
1 2010   158
2 2011   160
3 2012   157
4 2013   155

Notez que vous auriez pu lire directement PopReg.csv en ligne en faisant :

setInternet2(TRUE) # pour les url en https
PopReg <- read.csv("collez ce lien entre les guillemets")

Si vous souhaitez jouer avec de vraie données, jetez un œil par ici.

Aucun commentaire:

Enregistrer un commentaire