This book is in Open Review. I want your feedback to make the book better for you and other readers. To add your annotation, select some text and then click the on the pop-up menu. To see the annotations of others, click the in the upper right hand corner of the page

Cours 1 Fonctions bien sympatiques tres cher

Description : du R base, des fonctions de “base”, du tidyverse.
Pour du data.table voir le cours concerné.

ICI JE METS JUSTE LE NOM DES FONCTIONS, MAIS FAUT CHERCHER SUR INTERNET/LES PAGES D’AIDE LES MODALITES D’UTILISATION !!

1.1 Conseils

  • Eviter de donner le meme nom au pipe que la base qu’on utilise dedans, ça écrase les données, et c’est la galere pour les reccuperer

  • Les fonctions tidy sont pas faites pour s’imbriquer. Utiliser des fonctions base à l’int des fcts tidy.

  • Qd un prblm est trop gros, découper le travail (ex: faire des sous-tables)

1.2 Tips de codeur

  • Selectionner tout ce qu’il ya dans la parenthèse/crochet/accolade : double clic à l’interieur de la 1ère/dernière

  • Mesurer le temps d’exécution d’un code : system.time() ou microbenchmark (fct1,fct2) pour des codes trés courts. Ce sont les médianes des temps de calcul qu’il faut comparer.

start.time <- Sys.time()
# fonction appelée ici
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken
  • détacher un package de l’environnement : unloadNamespace()

  • connaitre le code d’une fct : trace(pkgname::fct, edit=T)

  • (obt <- code) : affiche l’objet

  • Empecher l’affichage d’un message d’erreur : try( , silent=TRUE) # no error printed

  • Progress bar : pb = txtProgressBar(min = 0, max = length(ind), style = 3) then close(pb)

  • debuger : traceback()

  • Tracer un warning : options(warn = 2) (le transforme en erreur) quand fin de debuger options(warn = 0)

  • mettre au propre un code (réindenter, ->, espaces, taille des lignes) : package “styler” > Addins > Style active file

  • créer une table de combinaisons de paramètres : tidyr::crossing(a, b, c)

1.3 Packages inédits!

  • Shiny pour trouver des packages R dans le milieu forestier : ForestAnalysisInR::launchRFA()

1.4 Mes raccourcis claviers

  • Tout selectionner : Ctrl + A

  • Sélection de texte : maj + flèche dans sens de selection (on peut délimiter avec clic souris)

  • Indenter : Ctrl + I

  • Recherche sur toutes les pages du projet : Ctrl + Shift + F (on peut faire du replace !)

  • %>% : Ctrl + Shift + M

  • %in% : Ctrl + Shift + I (nécéssite un package) Install the package: devtools::install_github(“rstudio/addinexamples”, type = “source”) Restart R

1.5 Symbol/name, charactères, variable/objet tout le bazar

my_summarise <- function(.data, ...) {
  .data %>%
    group_by(...) %>%
    summarise(mass = mean(mass, na.rm = TRUE), height = mean(height, na.rm = TRUE))
}
starwars %>% my_summarise(sex, gender)

1.6 Charger les données

  • Chemin absolu : écriture de l’entièreté du chemin

  • Chemin relatif :
    ~ = le dossier du setwd
    ./ = là où je suis
    Les .rmd ont leur propre racine, donc pas celle de leur projet.
    ” ../ = dossier parent (du niv de dessus) et je mets autant de ../ que de niveau à remonter.
    Puis tabulation pour qu’il propose mes fichiers.
    Stocker mon chemin relatif dans un objet « path ».
    Pour lire mon chemin stocké : file.path(path, “dossier”, “file”)

  • Pour ouvrir une fenetre pour choisir le fichier : nomObjt <- file.choose()

!!!!!!Environment > import dataset > tjrs spécifier le séparateur (delimiter) et le marqueur de décimale (locale > decimal mark)!!!!!!!!! (franchement ça fait trop de la m**rd sinon)

  • Importer avec les accents : locale = locale(encoding = “latin1”)

Importer tous les fichiers d’un dossier :

filenames <- list.files(path, pattern="*.csv", full.names=TRUE) # catch the name of all the files of the folder

df_list <- lapply(filenames, read.csv, header=FALSE, sep=";") # read all the folder files
  • lire du texte qui n’est pas une table : readLines()
  • Enregistrer

1.7 Exportation des données

  • en csv : write.csv(obj, “path/data.txt”)

  • en fichier texte : write.table(obj, “path/data.txt”,sep=“;”)

  • 1 object en r data : saveRDS(obj, file = “./folder/filename.rds”) puis objname <- readRDS(“./folder/filename.rds”)

  • plsrs objets : save(obj1, obj2, file = “./folder/filename.Rdata”) puis load(“./folder/filename.Rdata”)

  • tout l’environnement : save.image(file = “my_work_space.RData”) puis load(“my_work_space.RData”)

  • un renvoi consol :

sink("D:/Mes Donnees/PhD/Light/LAI-2200/DATA/Transmittance_cor.txt") # path
objt
sink() # close the external connection
  • en fichier Excel : **write.table(obj,“data.xls”,sep=“,row.names = F, dec=”,“)** il faut une tabulation”/t

  • Importer du shapefile (shp) :
    rgdal::readORG(dsn = “/path/to/your/file”, layer = “filename”) ou
    raster::shapefile(“path/to/your/file.shp”)

1.8 Correction préliminaires des données

  • Corriger les arbres non touvés mais vivants dans inventaires : package forestdata sur github ecofog

1.9 Transformation de données !

  • Supprimer une colonne/ligne vide : janitor::remove_empty(data,“cols”)

  • Renomer une variable : rename(New = Old)

  • Renames columns using a function (here add a suffix): **rename_with(.fn = ~paste0(., “_suffix”), .cols = c(“a”, “b”, “c”))**

  • De character à factor : mutate(Vernacular = factor(as.character(Vernacular)))

  • Séparer 1 colonne en plsrs : **separate(data, col à séparer, sep = “_“, into = c(nom des new col), remove = F)** remove = F pour conserver la colonne qu’on sépare

  • Combiner des colonnes en une : unite(col1, col2, col = “sp”, sep = ” “, remove = T)

  • La même qd ya pas de séparateur : mutate(variable = substr(x, start, stop)) ou
    StrLeft(x, n)
    StrRight(x, n) en partant de la fin. -n pour enlever n paramètre

  • Recoder une variable : mutate(var = recode(var, “old1” = “new1” , “old2” = “new2”)) le nouveau code derière le =
    si ya erreur essayer : “‘1’ = ‘A’ ; ‘2’ = ‘B’” guillemets double et simple et point virgule

  • Changer une variable sous condition : mutate(var = ifelse(condition, si oui, sinon))
    Sous plusieurs conditions : séparer les conditions d’un &

  • pour faire plusieurs ifelse pour le calcul d’une variable :

mutate(var = case_when(
  x == 1 ~ "A",
  x == 10 ~ "B",
  x == 20 ~ "C",
  .default = var) # le reste reste comme c'est
)
  • Changer le nombre de décimales : format(x, digits = 0, scientific = F) ou round(x, digits = 0)

  • Arrondir tout un df sur uniquement les variables numériques : mutate_if(is.numeric, round, digits = 2)

  • effectuer par ligne : rowwise()

  • Remplir une colonne à partir d’une fonction dont l’input est une table : do()

  • déplie la une sous-table existant dans une table : unnest()

  • Encode a column in utf8 : tidyft::utf8_encoding(datatable, colname)

  • Mettre à NA 10% du jeu de donnée aléatoirement : data[sample(nrow(data), 0.1 * nrow(data)), c(“X”, “Y”, “Z”) := NA_real_]

  • Calculate row means on subset of columns : mutate(Mean = rowMeans(select(., var1, var2)))

  • Standardiser pour sommer à 100% : **var/sum(Sum))*100**

  • joindre des tables : **left_join(dataB, by= c(“var1”, “var2”), suffix = c(“_A”, “_B”)))**

  • Replace each NA with the most recent non-NA prior to it : zoo::na.locf()

  • prendre toutes les colones : everything()

1.10 Histoire de characters

1.10.1 Create

  • paste(val, ” truc”, val, “truc”, “”, sep = “,”)

1.10.2 Detect

  • Detect special characters (logical) :
    x <- “!”
    grepl(‘[[:punct:]]’, x) # TRUE if there are any special character, FALSE if not.

  • Special pattern : grepl(“pattern”, var)

  • dot/point can be “\.”

1.10.3 Extract

  • Extraire un element numeric dans une chaîne de characters : readr::parse_number(var) ou gsub(“[[:digit:]]”, ““, var)

  • Extraire un élément d’une chaine de characters :
    substring(ID, first=1, last=2)

si data\(idtree = "site_plot" **data\)site = data.table::tstrsplit(data\(idtree, split = "_")[[1]]** 1er elmt **data\)plot = data.table::tstrsplit(data$idtree, split = “_“)[[2]]** 2nd

1.10.4 Convert

  • Mettre le nom d’un objet sous forme de characters : deparse(substitute(obj))

  • Afficher un data.frame en characters :

a <- data.frame(x=runif(4), y=runif(4), z=runif(4))
b <- capture.output(a)
c <- paste(b, "\n", sep="")
cat("Your data set is:\n", c, "\n")
  • Mettre en minuscule/majuscule : tolower()/toupper()
  • 1ère lettre de l’expression en majuscule : str_to_sentence()
  • Remplacer un pattern : str_replace(df$address, “St”, “Street”)

1.10.5 Remove

  • Remove specific pattern : str_remove(string, pattern)

  • Remove rows with a special pattern : filter(!grepl(“pattern”, var))

  • Remove whitespace : gsub(“[[:space:]]”, ““, x)

  • removes whitespace at the start and end, and replaces all internal whitespace with a single space : str_squish()

  • Remove parentheses : gsub(“[()]”, ““, my_string)

  • Remove brackets : gsub(“\[|\]”, ““, string)

  • Also remove text within () : **gsub(“\s*\([^\\)]+\)“,”“, my_string)**

  • Remove non-breaking space : gsub(“[^ -~]+”,““, x))

  • Remove special characters :
    x <- “a-,_b/”
    **gsub(“[[:punct:]]”, ““, x)** x la chaine de characters à modifier, entre” ” mettre par quoi remplacer les special charcters enlevés (ou ne rien mettre)

  • Enlever un espace avant et/ou apres un character : trimws(x, which = c(“both”, “left”, “right”))

  • Enlever accent : sub(“é”,“e”,vector))

1.11 Comparaison de tables

  • diffdf(,)

1.12 Tirage

  • Tirer aléatoirement n individus sans remplacement : sample_n(n, replace = F)

1.13 Yo ! arrange mes données !

## Quand tu veux passer une collone de df en argument de fonction :
## V0
column_name <- "Position" ## character string in an object
column <- inventory[,column_name] ## character vector
line_nonna <- which(!is.na(column)) ## which rows different of NA
subinventory <- inventory[line_nonna,] ## filter base version

## V1
column_name <- "Position"
column <- inventory[,column_name]
nonna <- !is.na(column) ## logical vector 
subinventory <- inventory[nonna,] ## take only the TRUE

## V2
column_name <- "Position"
inventory[!is.na(inventory[,column_name]),] %>%
  st_as_sf(wkt = column_name)

## Vdplyr
col_name <- deparse(substitute(var)) ## object name to this name in character(get() pour faire l'inverse)
inventory %>%
  filter(!is.na( {{ var }} )) %>% ## {{var}} pour réccupérer l'objet mis en argument "var"
  st_as_sf(wkt = col_name) ## quand t'as besoin du nom de la colonne en charactère

#ou

modif_var <- function(data, nom_variable){
  data %>% dplyr::mutate(nouveau_nom = !!rlang::sym(nom_variable)+1)
}
  • Inverser lignes & colonnes (retourner) (transposer) : t()

  • Mettre une colonne en colonne “rownames” : column_to_rownames(data, varàdéplacer)

  • Mettre “rownames” en colonne : tibble::rownames_to_column(“colname”)

  • Mettre l’information de plusieurs colonnes en 1 : melt()

  • Inverse : dcast(col1 + col2 ~ newcol)

  • Ne prendre qu’une partie des données : filter() ou subset()
    Si on veut garder les NA, comme filter les vire d’office, rajouter | is.na(var)

  • Pour filtrer beaucoup de valeurs d’une même var:

values <- c(“Tom”, “Lynn”) vecteur de n’importe quoi
filter(dat, var %in% values)

  • Ne pas prendre une partie des données (valeurs) : filter(!(Vernacular %in% remove)) (enlever remove dans vernacular)

  • Quand dans un booléen les Na dérangent, utiliser plutot %in% que == (ex: a %in% TRUE)

  • Enlever des colonnes : select(-colname)

  • Réaliser les opérations suivantes par groupes de modalités : group_by

  • Créer une variable résumant les effectifs des éléments d’une variable : summarise(N = n()) ou count(sp, sort = T,name = “N”) ou group_by(var) %>% mutate(N = n()) %>% ungroup() pour la mettre dans le df initial.

  • Calculer des stats de base par variable, et variables groupées :

HOBOdata %>%
  group_by(HoboID, Phase) %>% # variables selon lesquelles grouper
  summarise(across(c("Temp", "Light"), # Variables à analyser
                   list(mean = mean, # les stats
                        sd = sd,
                        max = max,
                        min = min)))

# si ya une variable qui a besoin d'autres variables :
phase_stats <- HOBOdata %>%
  group_by(HoboID, Phase) %>% 
  summarise(across(c("Temp", "Light"), 
                   list(mean = ~mean(.), 
                        sd = ~sd(.),
                        VarCoef = ~(sd(.) / mean(.)) * 100, # la var qui en utilise d'autres
                        max = ~max(.),
                        min = ~min(.)),
                   .names = "{.col}_{.fn}"))
# "Phase" variable as an index for the computed variables
phase_stats <- pivot_wider(phase_stats, names_from = Phase,
                           values_from = names(phase_stats)[-c(1:2)],
                           names_glue = "{.value}_{Phase}")
  • par ordre croissant (pour un vecteur!) : sort(x, decreasing = FALSE, na.last = NA, …) ou order()

  • Pour une col dans un dataframe : Effectifs par ordre croissant : arrange(N)

  • Effectifs par ordre décroissant : arrange(desc(N))

  • Ordonner des chiffres en character : gtools::mixedsort(sort(filenames))

  • Ranger par ordre alphabétique : d’abord transformer la variable character en factor, puis arrange(var)

  • Selectionner les n valeurs maximales : top_n

  • Afficher les 30 1ères lignes : slice(1:30)

  • Changer ordre des colonnes : select(c(a, y, x, 1ercolnonmodified : dercol))

  • Séparer une base de données, selon un facteur, en une liste de bases de données : split(data, data$fact)

  • Enlever les lignes en plusieurs exemplaires/connaitre les valeurs que peut prendre une colonnne : unique() ou que sur une variable : distinct(idTree, .keep_all = T)

  • Savoir si ttes les valeurs d’une colonne sont les mêmes: length(unique(data\(var)) == 1** ou **all(data\)var == data$var[1]) = est-ce que toutes les valeurs sont égales à la 1ère

  • Répliquer une ligne n fois : do.call(“rbind”, replicate(n, df, simplify = FALSE))

  • Populer les valeurs (si NA) pour une var groupée : group_by(TreeID) %>% fill(X, Guyafor.nb, ScientificName, .direction = “downup”)

  • Joindre 2 tables :

left_join(df1, df2, by = 'key', suffix = c("_1", "_2")) %>% # by = c('coldf1' = 'coldf2')) if not the same name
  mutate( # mutate sur plusieurs variables
    var1 = coalesce(var1.x, var1.y), # pour combiner les valeurs de .x et .y 
    var2 = coalesce(var2.x, var2.y)
  ) %>% 
  select(-(contains(".x") | contains(".y")))
  • Ne garder les lignes que sans NA dans n’importe quelle colonne : na.omit(df) ou df[!complete.cases(df), ]

  • Removing Rows with Only NAs : data[rowSums(is.na(data)) != ncol(data), ] ou filter(data, rowSums(is.na(data)) != ncol(data))

1.14 Donne moi des infos sur mes données

  • pH[pH>7] : afficher les ph>7
    length(pH[pH>7]) : combien de ph>7
    data[pH>7,] : afficher les lignes dont les ph>7

which(x==a) : renvoie les indices (n°de lignes) de x pour lesquels le résultat de l’opération logique est vrai

  • Indicer selon une modalité : data[data$var ==“modalite”,]

  • Nombre de NA dans 1 colonne : sum(is.na(data$x_num))

  • quelles colonne ont des NA : names(df)[sapply(df, anyNA)]

  • Nombre de lignes ayant pour valeur “truc” dans telle variable sum(as.numeric(data$var == “truc”), na.rm = TRUE) pcq as.numeric transforme un vecteur de booléen en vecteur de 0 et 1.

  • Nombre de NA dans le jeu de de données, dans chaque colonne : colSums(is.na(data))

  • est-ce que tt ça est vrai : all()

  • au moins 1 vrai : any() ne prend pas de liste (enfin si mais il n’est pas content)!

  • renvoyer les éléments dupliqué : duplicated() (booléen) data[duplicated(data$var), ] (dataframe)
    anyDuplicated

  • Générer la numérotation/les id des lignes : seq.int(nrow(df))

  • Nombre pair/impair : var %% 2 == F

1.15 Calcul informatif

  • Faire la somme/moyenne/autre de chaque ligne/colonne : apply(data, c(1,2), sum) 1 : par ligne ou 2 : par colonne

  • Appliquer une fonction sur une liste/vecteur : lapply(liste, function(elementdelaliste) la fonction dépendante de l’élement) ou lapply(liste, function, autres arguments de la fct)
    https://www.datacamp.com/tutorial/r-tutorial-apply-family ex :

multiply <- function(x, factor, div) {
  (x * factor)/div
}

lapply(list(1,2,3), multiply, x = 5, factor = 3) # the list is for the "div" argument
lapply(a, function(element) bcDiversity(element$N, q = 1, Correction = "Best"))

ptit tips : la version fonction d’extraction d’élément d’un objet ($) : getElement(object, var) ex :

lapply(x, function(x) x$var) 
=  
  lapply(x, function(x) getElement(x, "var"))  
=  
  lapply(x, getElement, "var") 
  • Appliquer une fonction sur plsrs listes/vecteurs : mapply(function(X,Y) {la fonction(X, Y)}, X=list1, Y=list2, SIMPLIFY = F)
    SIMPLIFY = F : laisse la structure initiale de la liste

  • map functions family font apriori la même chose que les apply avec plus de possiblités et + rapides car écrites en C (https://r4ds.had.co.nz/iteration.html)
    Les map ne produisent que des vecteurs, pas de matrice)

Quand onotre map ne fctne pas il ne renvoie rien. Pour savoir ce qu’il ne va pas : map(safely(fct)) qui renvoie le résultat et le message d’erreur

  • Appliquer une fonction par indices/catégorie : by(data, INDICES = colindex, fct)

1.16 Nettoyage

  • Enlever un élément de l’environement : remove()
  • Vider tt l’envrmt global : rm(list = ls()) ls() renvoie ts les objets de l’envmt

1.17 Boucle

  1. Output : créer un objet vide de la classe, voire de la taille que l’on souhaite pour notre output (+ rapide)
  • chaine de charactère vide : ““

  • vecteur/liste : vector(“numeric”, length(x)), ou juste vector(), list()

  • Quand on ne connait pas la longeur de l’output a priori, on peut l’aggrandir progressivement dans le corps de la boucle : output <- c(output, action qu’on boucle)
    ou on stocke les outputs de chaque itération dans un élément d’une liste crée en amont (vector(“list”, length(x))), puis qd la loop est finie on unlist (+efficace).
    En résumé pour les gros outputs, il vaut mieux créer des outputs plus légers à chaque iteration puis tout coller ensemble après la boucle (-lourd).

  1. Sequence : créer un vecteur dans lequel puiser s’il n’existe déjà
  • pour agir sur chaque col d’un df : seq_along(df)
  • boucler sur indice, value ou names
  1. Body : Pour chaque valeur que peut prendre trait dans All_traits :
    for(trait in All_traits){}
resultat <- rep(NA, 3)
for(i in seq_len(3)) {
  resultat[i] <- i
}
  • utiliser [[]] plutot que [] même pour les vecteurs

seq_along() : permet dans le cas où la sequence est de taille 0 ou 1 de bien avoir un output de cette taille sinon avec 1:length(1 ou 0) on optiendra 1 0 ou 1 1

  • faire une boucle dont les résultats sont mis dans une liste: foreach()

  • Boucle while : boucle jusq’à ce que la condition soit fausse. Peut être utilisée lorsqu’on ne connait pas la longueur de la séquence.

while (condition) {
  ## body
}
  • Arrêter la boucle : break()

  • Arreter l’itération actuelle et passer à la prochaine : next()

  • répéter jusqu’à ce qu’il n’y est plus d’erreur :

repeat { 
  # code
  if (!(inherits(test,"try-error"))) 
    break
}

1.18 Les objets

1.18.0.1 des infos sur mon objet

  • Présence d’une variable “varName” %in% names(df)
  • Type : class(a), pour ttes les variables d’une table lapply(data, class)
  • Structure : str(a, 1) 1 c’est le niveau de structure, yen a plsrs, c’est pas obligatoire

1.18.0.2 List

“a” la liste.
+ Voir les éléments de la liste : a$
+ Indicer une liste : a[[position]]

  • Transposer une liste (inverser la tructure) : purr::transpose()

1.18.0.3 Fonction

function(arguments){
  operation1
  operation2
  return()  ## préciser ce que la fonction doit renvoyer
}

1.19 Condition

Les if sont des booléens qui vérifient si la “condition” est “TRUE”, donc il n’est pas nécessaire “x == TRUE” mais seulement “x” ou “!x”
+ if(condition) {action}
+ if(condition1 && condition2) { expression }
+ if(condition1 || condition2) { expression }

  • Dans les if else la place des brackets est importante:
if(case1) {
  expression1
} else {
  expression2
}

if(case1) {
  expression1
} else if(case2) {
  expression2
}
...
else last.expression
  • ifelse(condition, expression1, expression2) vectorized version of the if() statement. Warning: ifelse() is designed to work with vectors and matrices – not data frames.

1.20 Logical Operators

c(T, F, T) | c(F, F, T) ## TRUE FALSE  TRUE

c(T, F, T) || c(F, F, T) ## TRUE

c(F, F, T) || c(F, F, T) ## FALSE

c(F, F, T) || c(T, F, T) ## TRUE

## |/& to compare each value of different bolean vectors
## ||/&& to compare single value conditions 

1.21 Stan - Modelo - Bayes

  • Chercher une fct dans Rstan : lookup(“bernoulli”)

1.22 Faire de la biblio comme une déesse

  • package bibliometrix

1.23 Date & time

  • Wrong system time : Sys.time() Sys.timezone()
    To find our time zone : OlsonNames()
    Set the new time zone : Sys.setenv(TZ = “America/Cayenne”)
    To change permanently : change time zone of your computer

  • Convert Julian Day to calendar date as.Date(Julian Day, origin = “2021-12-31”) to start the 2022-01-01

  • convertir une date (y, m, d) en année numeric : as.numeric(format(ExactDate, “%Y”))

  • convertir une chaine de charactère en date : as_date(col_Date, format = “%m/%d/%Y”)

  • convertir une chaine de charactère en heures : hms::as_hms(col_Hour) ou chron(times = col_Hour)

  • convertir une chaine de charactère en date-time :

  • lubridate::mdy_hms(Time, tz = “America/Cayenne”) mdy pour month, day, year, hms pour hour, minute, seconde. Modifier l’ordre des lettres selon votre format.

  • base::strptime(Time, format = “%Y.%m.%d %H:%M”, tz = “America/Cayenne”)

  • lubridate::as_datetime(, tz = “America/Cayenne”)

  • Convertir des heures en numériques (ex:2.5h) en hh:mm:ss : hms::hms(seconds_to_period(2.5 * 3600))

  • extraire d’un date_time : date(), year(), month(), day(), hour(), minute(), second(), format(Date_Time, format = “%H:%M:%S”)

  • filtrer selon un pas de temps :

Df1 %>%
  mutate(Time = mdy_hms((Time))) %>% # format: 2023-03-30 18:15:00
  filter(minute(Time) %in% c("00", "15", "30", "45")) # every 15 minutes
  • filter par date et heures séparément : filter(Date >= as.Date(“2023-03-30”) & Hour >= chron(times=“18:00:00”))

  • filter par date et heures au format Date-times : filter(Time >= mdy_hms(“03/30/2023 18:00:00”))

  • temps par ordre croissant data <- data[order(data$Time, decreasing = FALSE),]

  • calcul : Time = Time_UTC-(3 * 60 * 60) pour enlever 3h