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.takendé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
- nom d’objet -> ce nom en characteres : deparse(substitute(var))
- chaine de characteres -> nom d’objet : as.name(“name”)
- chaine de characteres -> objet : get(“var”) ou {{var}} ou … (https://dplyr.tidyverse.org/articles/programming.html) :
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 connectionen 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ètreRecoder 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 virguleChanger 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.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.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)
anyDuplicatedGé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" argumentptit 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 listemap 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
- 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).
- 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
- Body : Pour chaque valeur que peut prendre trait dans All_traits :
for(trait in All_traits){}
- 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.
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 :
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.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.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 computerConvert Julian Day to calendar date as.Date(
Julian Day, origin = “2021-12-31”) to start the 2022-01-01convertir 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 minutesfilter 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