Calculer des accroissements à l'intérieur d'une variable

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Sylvain Gaudin
Messages : 25
Enregistré le : 10 Jan 2017, 06:41

Calculer des accroissements à l'intérieur d'une variable

Messagepar Sylvain Gaudin » 27 Avr 2022, 16:27

Bonjour,

J'ai des données présentées sous la forme suivante :

Code : Tout sélectionner

Placette <- as.factor(c(1,1,1,2,2,1,1,1,2,2,2))
Arbre <- as.factor(c(1,2,3,1,2,1,2,3,1,2,3))
Diametre <- c(51,27,38,75,55,54,24,NA,77,58,37)
Annee <- as.factor(c("2017","2017","2017","2017","2017","2022","2022","2022","2022","2022","2022"))
Statut <- as.factor(c("G","G","M","G","G","G","G","M","G","G","N"))

df <- data.frame(Placette, Arbre, Diametre, Annee, Statut)



Le Statut correspond au statut de l'arbre (G : gardé, M : enlevé et N : nouveau). Chaque arbre gardé a une mesure de diamètre pour l'année 2017 et une pour l'année 2022. Je cherche à calculer l'accroissement pour chaque arbre gardé, c'est-à-dire la différence entre le Diamètre en 2022 et celui en 2017.
J'ai essayé en utilisant la bibliothèque "tidyverse", mais je bloque rapidement :

Code : Tout sélectionner

library(tidyverse)

Accroissement <- df %>%
  group_by(Annee, Placette, Arbre, Statut) %>%
  mutate(Acc = max(Diametre) - min(Diametre))


Je ne vois pas comment faire le calcul des accroissements ensuite (ce qui est ci-dessus ne fonctionne pas et ne donne que des zéros et un NA). Faut-il passer par une variable D2017 et D2022 ? Merci pour votre aide.

Pierre-Yves Berrard
Messages : 1029
Enregistré le : 12 Jan 2016, 23:30

Re: Calculer des accroissements à l'intérieur d'une variable

Messagepar Pierre-Yves Berrard » 27 Avr 2022, 17:35

Bonjour,

Une solution (ne groupe pas par année et utilise dplyr::lag) :

Code : Tout sélectionner

df %>%
  group_by(Placette, Arbre, Statut) %>%
  arrange(Annee) %>%
  mutate(Acc = Diametre - lag(Diametre)) %>%
  ungroup()
PY

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: Calculer des accroissements à l'intérieur d'une variable

Messagepar Mickael Canouil » 27 Avr 2022, 18:47

Bonjour,

j'ajoute l'approche base et data.table (même résultat à l'ordre des lignes près).

Code : Tout sélectionner

df <- data.frame(
  
Placette = as.factor(c(1,1,1,2,2,1,1,1,2,2,2)),
  
Arbre = as.factor(c(1,2,3,1,2,1,2,3,1,2,3)),
  
Diametre c(51,27,38,75,55,54,24,NA,77,58,37),
  
Annee = as.factor(c("2017","2017","2017","2017","2017","2022","2022","2022","2022","2022","2022")),
  
Statut = as.factor(c("G","G","M","G","G","G","G","M","G","G","N"))
)

library(data.table)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:data.table':
#> 
#>     between, first, last
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
plot(bench::mark(
  
"base" = {
    do.
call("rbind"by(dfdf[c("Placette""Arbre""Statut")], function(.df) {
      
vec <- .df[order(.df[["Annee"]]), "Diametre"]
      .
df[["Acc"]] <- vec stats::lag(vec)
      .
df
    
}))
  },
  
"dplyr" = {
    
df %>%
      
dplyr::group_by(PlacetteArbreStatut) %>%
      
dplyr::arrange(Annee) %>%
      
dplyr::mutate(Acc Diametre dplyr::lag(Diametre)) %>%
      
dplyr::ungroup()
  },
  
"data.table" = {
    
data.table::as.data.table(df)[
      
order(Annee),
      
Acc := Diametre data.table::shift(Diametre),
      
by c("Placette""Arbre""Statut")
    ]
  },
  
check FALSE
))
#> Loading required namespace: tidyr 


Image
Mickaël
mickael.canouil.fr | rlille.fr

Sylvain Gaudin
Messages : 25
Enregistré le : 10 Jan 2017, 06:41

Re: Calculer des accroissements à l'intérieur d'une variable

Messagepar Sylvain Gaudin » 28 Avr 2022, 07:08

Pierre-Yves Berrard a écrit :Bonjour,

Une solution (ne groupe pas par année et utilise dplyr::lag) :

Code : Tout sélectionner

df %>%
  group_by(Placette, Arbre, Statut) %>%
  arrange(Annee) %>%
  mutate(Acc = Diametre - lag(Diametre)) %>%
  ungroup()


Merci beaucoup pour cette réponse. Je ne connaissais pas la fonction dplyr::lag qui s'avère très efficace et l'aide "copier avec des valeurs décalées à droite" m'apparaissait peu explicite dans ce cas.
Il me reste un petit soucis. La sortie de R donne :

Code : Tout sélectionner

# A tibble: 11 × 6
   Placette Arbre Diametre Annee Statut   Acc
   <fct>    <fct>    <dbl> <fct> <fct>  <dbl>
 1 1        1           51 2017  G         NA
 2 1        2           27 2017  G         NA
 3 1        3           38 2017  M         NA
 4 2        1           75 2017  G         NA
 5 2        2           55 2017  G         NA
 6 1        1           54 2022  G          3
 7 1        2           24 2022  G         -3
 8 1        3           NA 2022  M         NA
 9 2        1           77 2022  G          2
10 2        2           58 2022  G          3
11 2        3           37 2022  N         NA


Je souhaite récupérer la dernière colonne Acc dans mon dataframe initial (df) et je n'y arrive pas. La commande suivante ne fonctionne pas.

Code : Tout sélectionner

df$Acc <- Acc
Erreur : objet 'Acc' introuvable

Sylvain Gaudin
Messages : 25
Enregistré le : 10 Jan 2017, 06:41

Re: Calculer des accroissements à l'intérieur d'une variable

Messagepar Sylvain Gaudin » 28 Avr 2022, 07:09

Mickael Canouil a écrit :Bonjour,

j'ajoute l'approche base et data.table (même résultat à l'ordre des lignes près).


Merci beaucoup Mickael. Je prendrai le temps de tester ces différentes approches. Je dois refaire de calculs d'accroissement sur plusieurs tableaux de données dans les semaines qui viennent.

Pierre-Yves Berrard
Messages : 1029
Enregistré le : 12 Jan 2016, 23:30

Re: Calculer des accroissements à l'intérieur d'une variable

Messagepar Pierre-Yves Berrard » 28 Avr 2022, 09:15

Sylvain Gaudin a écrit :Je souhaite récupérer la dernière colonne Acc dans mon dataframe initial (df) et je n'y arrive pas. La commande suivante ne fonctionne pas.

Code : Tout sélectionner

df$Acc <- Acc
Erreur : objet 'Acc' introuvable

Il serait dangereux ici d'insérer de la sorte un vecteur dans la table initiale car l'ordre des lignes a potentiellement été changé (par arrrange).

Une solution plus simple et plus sûre est d'affecter le résultat :

Code : Tout sélectionner


df 
<-
  df %>%
  group_by(Placette, Arbre, Statut) %>%
  arrange(Annee) %>%
  mutate(Acc = Diametre - lag(Diametre)) %>%
  ungroup()
PY

Sylvain Gaudin
Messages : 25
Enregistré le : 10 Jan 2017, 06:41

Re: Calculer des accroissements à l'intérieur d'une variable

Messagepar Sylvain Gaudin » 28 Avr 2022, 12:08

Merci beaucoup, je me compliquais effectivement la vie inutilement.

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Calculer des accroissements à l'intérieur d'une variable

Messagepar Logez Maxime » 28 Avr 2022, 15:40

Bonjour,

avec les fonctions de base pour être sur de conserver le même ordre qu'au départ tu peux utiliser la fonction ave :

Code : Tout sélectionner

df$acc <- ave(df$Diametre, do.call(interaction, df[c(1,2,5)]), FUN = function(x)  x - lag(x))

Cordialement,
Maxime


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité

cron