R avancé et introduction à Git

Raphaël Nedellec

Données, Texte, Dates

Lire des données

Fichiers plats (.txt, .csv)

Traditionnellement, les fichiers de données de petite taille sont disponibles au format .csv ou .txt

# base R
read.csv()
read.table()
# R package readr
readr::read_csv()
# autres solutions :
data.table::fread()
vroom::vroom()
arrow::read_csv()

Warning

Même s’il est possible d’importer des données directement depuis RStudio, il est primordial de coder les imports pour rendre les études reproductibles.

Fichiers .json

Format omni-présent sur le web. Permet de représenter des données hiérarchiques.

{"employees":[
  { "firstName":"John", "lastName":"Doe" },
  { "firstName":"Anna", "lastName":"Smith" },
  { "firstName":"Peter", "lastName":"Jones" }
]}

Pour lire les fichiers json, on utilisera en priorité la librairie jsonlite.

library(jsonlite)
read_json("some_json_file.json")
?fromJSON()
?toJSON()

Possibilité de lire et écrire du json depuis R.

Lire un fichier parquet

Format parquet, très utilisé pour le traitement des “big data”.

library(arrow)

data(mtcars)
arrow::read_parquet()
arrow::write_parquet()
  • Stockage orienté colonne
  • Fichier binaire compressé, efficient et typé
  • Devient très courant - format de référence dans les data lake, lisible en python (pandas.read_parquet)

Requêter une base de données

Enfin, de nos jours, beaucoup de données d’analyse résident dans des bases de données, souvent dites relationnelles.

En R, le backend DBI a été développé pour fournir une interface unique à de nombreux systèmes de bases de données ou data warehouse existants : mysql, postgresql, snowflake, etc.

library(DBI)
# Create an ephemeral in-memory RSQLite database
con <- dbConnect(RSQLite::SQLite(), dbname = ":memory:")

dbListTables(con)
dbWriteTable(con, "mtcars", mtcars)
dbListTables(con)

dbDisconnect(con)

Requêter une base de données

library(DBI)
# Create an ephemeral in-memory RSQLite database
con <- dbConnect(RSQLite::SQLite(), dbname = ":memory:")

dbListTables(con)
#> character(0)
dbWriteTable(con, "mtcars", mtcars)
dbListTables(con)
#> [1] "mtcars"
dbListFields(con, "mtcars")
#>  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
#> [11] "carb"

Requêter une base de données

head(dbReadTable(con, "mtcars"))
res <- dbSendQuery(con, "SELECT * from mtcars LIMIT 6")
dbFetch(res)

Requêter une base de données

head(dbReadTable(con, "mtcars"))
#>    mpg cyl disp  hp drat    wt  qsec vs am gear carb
#> 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
#> 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
#> 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
#> 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
#> 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
#> 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
res <- dbSendQuery(con, "SELECT * from mtcars LIMIT 6")
dbFetch(res)
#>    mpg cyl disp  hp drat    wt  qsec vs am gear carb
#> 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
#> 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
#> 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
#> 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
#> 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
#> 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
dbClearResult(res)
dbDisconnect(con)

Manipulation de dataframes

data.frame

En R, les data.frame sont un élément essentiel du succès du langage pour le traitement des données.

df <- data.frame(col1 = c(1, 2, 3), col2 = c("a", "b", "c"))
class(df)
#> [1] "data.frame"
str(df, 1)
#> 'data.frame':    3 obs. of  2 variables:
#>  $ col1: num  1 2 3
#>  $ col2: chr  "a" "b" "c"

tibble

library(dplyr)

data(starwars)
class(starwars)
#> [1] "tbl_df"     "tbl"        "data.frame"
head(starwars, 4)
#> # A tibble: 4 × 14
#>   name         height  mass hair_…¹ skin_…² eye_c…³ birth…⁴ sex   gender homew…⁵
#>   <chr>         <int> <dbl> <chr>   <chr>   <chr>     <dbl> <chr> <chr>  <chr>  
#> 1 Luke Skywal…    172    77 blond   fair    blue       19   male  mascu… Tatooi…
#> 2 C-3PO           167    75 <NA>    gold    yellow    112   none  mascu… Tatooi…
#> 3 R2-D2            96    32 <NA>    white,… red        33   none  mascu… Naboo  
#> 4 Darth Vader     202   136 none    white   yellow     41.9 male  mascu… Tatooi…
#> # … with 4 more variables: species <chr>, films <list>, vehicles <list>,
#> #   starships <list>, and abbreviated variable names ¹​hair_color, ²​skin_color,
#> #   ³​eye_color, ⁴​birth_year, ⁵​homeworld

tibble

class(starwars) <- "data.frame"
head(starwars, 4)
#>             name height mass hair_color  skin_color eye_color birth_year  sex
#> 1 Luke Skywalker    172   77      blond        fair      blue       19.0 male
#> 2          C-3PO    167   75       <NA>        gold    yellow      112.0 none
#> 3          R2-D2     96   32       <NA> white, blue       red       33.0 none
#> 4    Darth Vader    202  136       none       white    yellow       41.9 male
#>      gender homeworld species
#> 1 masculine  Tatooine   Human
#> 2 masculine  Tatooine   Droid
#> 3 masculine     Naboo   Droid
#> 4 masculine  Tatooine   Human
#>                                                                                                                                       films
#> 1                                           The Empire Strikes Back, Revenge of the Sith, Return of the Jedi, A New Hope, The Force Awakens
#> 2                    The Empire Strikes Back, Attack of the Clones, The Phantom Menace, Revenge of the Sith, Return of the Jedi, A New Hope
#> 3 The Empire Strikes Back, Attack of the Clones, The Phantom Menace, Revenge of the Sith, Return of the Jedi, A New Hope, The Force Awakens
#> 4                                                              The Empire Strikes Back, Revenge of the Sith, Return of the Jedi, A New Hope
#>                             vehicles                starships
#> 1 Snowspeeder, Imperial Speeder Bike X-wing, Imperial shuttle
#> 2                                                            
#> 3                                                            
#> 4                                             TIE Advanced x1

tibble

class(starwars) <- "data.frame"
head(starwars, 4)

tibble

  • tibble surcharge les data.frame classiques
  • meilleur print, meilleurs “défauts”
class(starwars[, 1])
class(as.tibble(starwars)[, 1])

tibble

  • tibble surcharge les data.frame classiques
  • meilleur print, meilleurs “défauts”
class(starwars[, 1])
#> [1] "character"
class(as_tibble(starwars)[, 1])
#> [1] "tbl_df"     "tbl"        "data.frame"
  • tibble renvoie une data.frame à une colonne
  • data.frame renvoie un vecteur

dplyr

dplyr

starwars %>% 
  filter(species == "Droid")

dplyr

starwars %>% 
  filter(species == "Droid")
#> # A tibble: 6 × 14
#>   name   height  mass hair_color skin_color eye_c…¹ birth…² sex   gender homew…³
#>   <chr>   <int> <dbl> <chr>      <chr>      <chr>     <dbl> <chr> <chr>  <chr>  
#> 1 C-3PO     167    75 <NA>       gold       yellow      112 none  mascu… Tatooi…
#> 2 R2-D2      96    32 <NA>       white, bl… red          33 none  mascu… Naboo  
#> 3 R5-D4      97    32 <NA>       white, red red          NA none  mascu… Tatooi…
#> 4 IG-88     200   140 none       metal      red          15 none  mascu… <NA>   
#> 5 R4-P17     96    NA none       silver, r… red, b…      NA none  femin… <NA>   
#> 6 BB8        NA    NA none       none       black        NA none  mascu… <NA>   
#> # … with 4 more variables: species <chr>, films <list>, vehicles <list>,
#> #   starships <list>, and abbreviated variable names ¹​eye_color, ²​birth_year,
#> #   ³​homeworld

dplyr

starwars %>% 
  select(name, ends_with("color"))

dplyr

starwars %>% 
  select(name, ends_with("color"))
#> # A tibble: 87 × 4
#>    name               hair_color    skin_color  eye_color
#>    <chr>              <chr>         <chr>       <chr>    
#>  1 Luke Skywalker     blond         fair        blue     
#>  2 C-3PO              <NA>          gold        yellow   
#>  3 R2-D2              <NA>          white, blue red      
#>  4 Darth Vader        none          white       yellow   
#>  5 Leia Organa        brown         light       brown    
#>  6 Owen Lars          brown, grey   light       blue     
#>  7 Beru Whitesun lars brown         light       blue     
#>  8 R5-D4              <NA>          white, red  red      
#>  9 Biggs Darklighter  black         light       brown    
#> 10 Obi-Wan Kenobi     auburn, white fair        blue-gray
#> # … with 77 more rows

dplyr

starwars %>% 
  mutate(name, bmi = mass / ((height / 100)  ^ 2)) %>%
  select(name:mass, bmi)

dplyr

starwars %>% 
  mutate(name, bmi = mass / ((height / 100)  ^ 2)) %>%
  select(name:mass, bmi)
#> # A tibble: 87 × 4
#>    name               height  mass   bmi
#>    <chr>               <int> <dbl> <dbl>
#>  1 Luke Skywalker        172    77  26.0
#>  2 C-3PO                 167    75  26.9
#>  3 R2-D2                  96    32  34.7
#>  4 Darth Vader           202   136  33.3
#>  5 Leia Organa           150    49  21.8
#>  6 Owen Lars             178   120  37.9
#>  7 Beru Whitesun lars    165    75  27.5
#>  8 R5-D4                  97    32  34.0
#>  9 Biggs Darklighter     183    84  25.1
#> 10 Obi-Wan Kenobi        182    77  23.2
#> # … with 77 more rows

dplyr

starwars %>% 
  arrange(desc(mass))

dplyr

starwars %>% 
  arrange(desc(mass))
#> # A tibble: 87 × 14
#>    name        height  mass hair_…¹ skin_…² eye_c…³ birth…⁴ sex   gender homew…⁵
#>    <chr>        <int> <dbl> <chr>   <chr>   <chr>     <dbl> <chr> <chr>  <chr>  
#>  1 Jabba Desi…    175  1358 <NA>    green-… orange    600   herm… mascu… Nal Hu…
#>  2 Grievous       216   159 none    brown,… green,…    NA   male  mascu… Kalee  
#>  3 IG-88          200   140 none    metal   red        15   none  mascu… <NA>   
#>  4 Darth Vader    202   136 none    white   yellow     41.9 male  mascu… Tatooi…
#>  5 Tarfful        234   136 brown   brown   blue       NA   male  mascu… Kashyy…
#>  6 Owen Lars      178   120 brown,… light   blue       52   male  mascu… Tatooi…
#>  7 Bossk          190   113 none    green   red        53   male  mascu… Trando…
#>  8 Chewbacca      228   112 brown   unknown blue      200   male  mascu… Kashyy…
#>  9 Jek Tono P…    180   110 brown   fair    blue       NA   male  mascu… Bestin…
#> 10 Dexter Jet…    198   102 none    brown   yellow     NA   male  mascu… Ojom   
#> # … with 77 more rows, 4 more variables: species <chr>, films <list>,
#> #   vehicles <list>, starships <list>, and abbreviated variable names
#> #   ¹​hair_color, ²​skin_color, ³​eye_color, ⁴​birth_year, ⁵​homeworld

dplyr

starwars %>%
  group_by(species) %>%
  summarise(
    n = n(),
    mass = mean(mass, na.rm = TRUE)
  ) %>%
  filter(
    n > 1,
    mass > 50
  )

dplyr

starwars %>%
  group_by(species) %>%
  summarise(
    n = n(),
    mass = mean(mass, na.rm = TRUE)
  ) %>%
  filter(
    n > 1,
    mass > 50
  )
#> # A tibble: 8 × 3
#>   species      n  mass
#>   <chr>    <int> <dbl>
#> 1 Droid        6  69.8
#> 2 Gungan       3  74  
#> 3 Human       35  82.8
#> 4 Kaminoan     2  88  
#> 5 Mirialan     2  53.1
#> 6 Twi'lek      2  55  
#> 7 Wookiee      2 124  
#> 8 Zabrak       2  80

Données textuelles

Manipulation de chaines de caractères

Élément important des tâches de manipulation de données, de nettoyage, de transformation, souvent basé sur les expressions régulières.

En R base, possibilité de manipuler des chaînes de caractères, mais :

  • API des fonctions inconsistantes
  • naming difficile à comprendre
  • documentation parfois cryptique

Manipulation de chaines de caractères

Élément important des tâches de manipulation de données, de nettoyage, de transformation, souvent basé sur les expressions régulières.

En R base, possibilité de manipuler des chaînes de caractères, mais :

  • API des fonctions inconsistantes
  • naming difficile à comprendre
  • documentation parfois cryptique
  • une librairie user friendly : stringr

Expressions régulières

Simple match :

library(stringr)
x <- c("apple", "banana", "pear")
str_view(x, "an")

Expressions régulières

“.” match tous les caractères

x <- c("apple", "banana", "pear")
str_view(x, ".a.")

Expressions régulières

Escaping avec le symbole \ :

str_view(c("abc", "a.c", "bef"), "a\\.c")

Expressions régulières

  • \d : match tous les symboles numériques
str_view_all("10 + 20 = 30", "\\d+")

Expressions régulières

  • \s : caractères d’espacement
(text <- "Some  \t badly\n\t\tspaced \f text")
#> [1] "Some  \t badly\n\t\tspaced \f text"
str_replace_all(text, "\\s+", " ")
#> [1] "Some badly spaced text"

Expressions régulières

  • \w et \W : mots
str_extract_all("Don't eat that!", "\\w+")[[1]]
#> [1] "Don"  "t"    "eat"  "that"
str_split("Don't eat that!", "\\W")[[1]]
#> [1] "Don"  "t"    "eat"  "that" ""

Expressions régulières

  • [abc] : match a, b, c
  • [a-z] : match tous les caractères minuscules
  • [^abc] : match tous les caractères exceptés a, b, c
  • [\^\-] : match les caractères ^ et -

Expressions régulières

  • [abc] : match a, b, c
  • [a-z] : match tous les caractères minuscules
  • [^abc] : match tous les caractères exceptés a, b, c
  • [\^\-] : match les caractères ^ et -

Voir R et expressions régulières

Fonctions stringr vs R base

stringr base R
str_detect(string, pattern) grepl(pattern, x)
str_dup(string, times) strrep(x, times)
str_extract(string, pattern) regmatches(x, m = regexpr(pattern, text))
str_extract_all(string, pattern) regmatches(x, m = gregexpr(pattern, text))
str_length(string) nchar(x)

Fonctions stringr vs R base

stringr base R
str_locate(string, pattern) regexpr(pattern, text)
str_locate_all(string, pattern) gregexpr(pattern, text)
str_match(string, pattern) regmatches(x, m = regexec(pattern, text))
str_order(string) order(…)
str_replace(string, pattern, replacement) sub(pattern, replacement, x)
str_replace_all(string, pattern, replacement) gsub(pattern, replacement, x)
stringr base R
str_sort(string) sort(x)
str_split(string, pattern) strsplit(x, split)
str_sub(string, start, end) substr(x, start, stop)
str_subset(string, pattern) grep(pattern, x, value = TRUE)
str_to_lower(string) tolower(x)
str_to_title(string) tools::toTitleCase(text)
str_to_upper(string) toupper(x)
str_trim(string) trimws(x)
str_which(string, pattern) grep(pattern, x)
str_wrap(string) strwrap(x)

Données calendaires

Unix time

L’heure Unix ou heure Posix est une mesure du temps fondée sur le nombre de secondes écoulées depuis le 1er janvier 1970 00:00:00 UTC, hors secondes intercalaires. Elle est utilisée principalement dans les systèmes qui respectent la norme POSIX, dont les systèmes de type Unix, d’où son nom. C’est la représentation POSIX du temps.

Timezone & UTC

Est-ce une date valide ?

"2022-01-01 03:40:54"
  • Importance des timezones
  • Universal Time Coordinated

UTC

Le temps universel coordonné ou UTC (en anglais : coordinated universal time) est une échelle de temps adoptée comme base du temps civil international par la majorité des pays du globe.

R base vs lubridate

Les dates sont des objets très fréquents et essentiels dans de multiple projets de datascience :

  • séries temporelles
  • données et messages horodatés

Il est possible de manipuler des objets de date en R base, mais lubridate propose une API plus consistante et accessible et peut faciliter vos traitements de données.

“Parsing” de dates

ymd(
  ...,
  quiet = FALSE,
  tz = NULL,
  locale = Sys.getlocale("LC_TIME"),
  truncated = 0
)

Exemple :

library(lubridate)
date <- ymd("2020-02-22")
str(date)
#>  Date[1:1], format: "2020-02-22"

Extraction d’éléments

date <- ymd("2020-02-22")
year(date)
month(date)
isoweek(date)
minute(date)

Extraction d’éléments

date <- ymd("2020-02-22")
year(date)
#> [1] 2020
month(date)
#> [1] 2
isoweek(date)
#> [1] 8
minute(date)
#> [1] 0

Extraction d’éléments

date <- ymd("2020-02-22")
wday(date)
Sys.setlocale(category = "LC_ALL", locale = "de_DE.UTF-8")
date <- ymd("2020-02-22")
wday(date, label = TRUE, abbr = FALSE)
Sys.setlocale(category = "LC_ALL", locale = "en_US.UTF-8")

Extraction d’éléments

date <- ymd("2020-02-22")
wday(date)
#> [1] 7
Sys.setlocale(category = "LC_ALL", locale = "de_DE.UTF-8")
#> [1] "de_DE.UTF-8/de_DE.UTF-8/de_DE.UTF-8/C/de_DE.UTF-8/en_US.UTF-8"
date <- ymd("2020-02-22")
wday(date, label = TRUE, abbr = FALSE)
#> [1] Samstag
#> 7 Levels: Sonntag < Montag < Dienstag < Mittwoch < Donnerstag < ... < Samstag
format_ISO8601(as.POSIXct("2018-02-01 03:04:05", tz = "EST"), usetz = TRUE)
#> [1] "2018-02-01T03:04:05-0500"

Interval, duration, period

  • interval : période temporelle entre deux dates
  • duration : durée définie en temps calendaire “humain” : en jours, en semaines, en mois..
  • period : durée définie en nombre de secondes

Questions ?