Somme d'une colonne selon les modalités d'un facteur

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

Romain Georges
Messages : 3
Enregistré le : 15 Déc 2022, 07:21

Somme d'une colonne selon les modalités d'un facteur

Messagepar Romain Georges » 19 Déc 2022, 09:04

Bonjour,

Je cherche à réaliser une opération sûrement très simple mais j'ai essayé plusieurs fonctions sans succès et je ne trouve la réponse nul part (peut être n'utilise-je pas les bons termes).

Je dispose d'un tableau de données compilant des piégeages d'insectes avec la structure suivante :

Code : Tout sélectionner

> summary(data)
    Bloc           Trap          Rep        Session          Date_in   
 Bloc1:108   Biobest :108   Min.   :1   Session1:108   03/10/2022:108 
 Bloc2:108   Droframb:108   1st Qu.:1   Session2:108   07/10/2022:108 
 Bloc3:108   HomeMade:108   Median :2   Session3:108   12/10/2022:108 
                            Mean   :2                                 
                            3rd Qu.:3                                 
                            Max.   :3                                 
       Date_out        Sp           Nb                   X     
 07/10/2022:108   Dother:81   Min.   :  0.00              :320 
 12/10/2022:108   Dsuz_f:81   1st Qu.:  4.00   Piege plein:  4 
 17/10/2022:108   Dsuz_m:81   Median : 11.00                   
                  Other :81   Mean   : 26.15                   
                              3rd Qu.: 30.00                   
                              Max.   :528.00 


Code : Tout sélectionner

> head(data)
   Bloc     Trap Rep  Session    Date_in   Date_out     Sp Nb X
1 Bloc1 HomeMade   1 Session1 03/10/2022 07/10/2022 Dsuz_f 42 
2 Bloc1 HomeMade   1 Session1 03/10/2022 07/10/2022 Dsuz_m 23 
3 Bloc1 HomeMade   1 Session1 03/10/2022 07/10/2022 Dother 12 
4 Bloc1 HomeMade   1 Session1 03/10/2022 07/10/2022  Other  4 
5 Bloc1 HomeMade   2 Session1 03/10/2022 07/10/2022 Dsuz_f 25 
6 Bloc1 HomeMade   2 Session1 03/10/2022 07/10/2022 Dsuz_m 18


Par exemple, ici les 4 premières lignes correspondent à 4 espèces/groupe d'espèces (colonne Sp) d'un même échantillon (identifié par les colonnes Bloc, Trap, Rep, Session, Date_in, Date_out).

Je cherche pour chaque échantillon à regrouper les modalités Dsuz_f et Dsuz_m de "Sp" en une modalité Dsuz qui comporterait dans la colonne "Nb" la somme des 2 valeurs initiales (ici 65 pour Rep 1, puis 43 pour Rep 2).

Auriez vous une solution?

Merci d'avance pour votre aide !

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

Re: Somme d'une colonne selon les modalités d'un facteur

Messagepar Logez Maxime » 19 Déc 2022, 09:23

Bonjour,

Avec la librairie dplyr tu peux faire :

Code : Tout sélectionner

dta %>%
  mutate(Sp = sub("Dsuz.*$", "Dsuz", Sp)) %>%
  group_by_at(1:7) %>%
  summarise(Nb = sum(Nb))


Cordialement,
Maxime

Romain Georges
Messages : 3
Enregistré le : 15 Déc 2022, 07:21

Re: Somme d'une colonne selon les modalités d'un facteur

Messagepar Romain Georges » 19 Déc 2022, 12:02

Génial, merci pour la réponse rapide qui fonctionne à merveille !

Faut que je décortique ton code pour comprendre ce que fait chaque ligne, j'avais commencé à chercher du côté de dplyr mais j'étais loin de trouver la solution..

Encore merci !

Romain

Maxime Deniaux
Messages : 70
Enregistré le : 11 Fév 2022, 22:49
Contact :

Re: Somme d'une colonne selon les modalités d'un facteur

Messagepar Maxime Deniaux » 19 Déc 2022, 14:06

Salut Romain (ou Georges ?),

essayer de trouver une solution avec dplyr était une bonne idée !

La fonction sub() permet de changer une valeur dans une chaîne de caractères. En l'occurrence, ici ce sont les éléments (les chaînes de caractères) de la colonne Sp.

sub("chocolat", "chocolat noir", "J'aime le chocolat") renverra "J'aime le chocolat noir"

A la place de "chocolat", Maxime utilise ce qu'on appelle une 'regex' (regular expression) avec le ".*$", qui va permettre en une ligne de décomposer les cas que tu as mentionné. Donc la fonction va rechercher dans la colonne Sp, les valeurs Dsuz_m et Dsuz_f et va les remplacer par Dsuz.

Les regex, ce n'est pas le truc le plus évident à maitriser (moi-même je ne maitrise pas...), mais c'est quelque chose d'assez connu, tu trouveras facilement du contenu dessus.

Si jamais c'est trop difficile pour toi et que tu connais en amont toutes les valeurs que tu souhaites remplacer (et qu'il n'y en a pas 600....), tu peux mettre :

Code : Tout sélectionner

mutate( Sp = case_when(Sp == "Dsuz_m" ~ Dsuz,
                       Sp == "Dsuz_f" ~ Dsuz
                      )


ce qui sera sûrement plus intuitif pour toi.

ou encore...faire les modifications en amont du code proposé par Maxime avec :

Code : Tout sélectionner

data$Sp[data$Sp == "Dsuz_m"] = Dsuz
data$Sp[data$Sp == "Dsuz_f"] = Dsuz


Sachant qu'en faisant cela, il n'y aura plus besoin du mutate puisque les modifications auront été faites avant.

Plein de solutions possibles...les joies du code ;)

Concernant group_by_at(), je ne connais pas. Je ne connais que group_by(), j'imagine que si tu mets group_by(Bloc,Trap,Rep,Session,Date_in,Date_out,Sp), tu auras le même résultat.
(group_by() te permet de grouper des variables pour faire des opérations dessus).

Enfin, summarise intervient la plupart du temps après un group_by() puisqu'il permet d'effectuer ces opérations , ici la somme des valeurs de Nb, par groupe mentionné (group_by).

En espérant que ce soit plus clair :)

Bonne fin de journée

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

Re: Somme d'une colonne selon les modalités d'un facteur

Messagepar Logez Maxime » 19 Déc 2022, 20:44

Maxime Deniaux a écrit :Maxime utilise ce qu'on appelle une 'regex' (regular expression) avec le ".*$", qui va permettre en une ligne de décomposer les cas que tu as mentionné.

En français on parle d'expressions régulières. Le "." remplace n'importe quel caractère, le "*" est un quantifieur qui dit de 0 à l'infini et le "$" marque la fin d'une chaîne de caractère. Autrement dit "Dsuz.*$" veut dire toutes les chaînes de caractères qui contiennent "Dsuz" suivi de quelque chose ou non. C'est ces chaînes la qui sont ensuite remplacer par "Dsuz", ça évite de donner tous les cas de figures possibles ou rencontrés.

Je pense que le code suivant est incomplet et qu'il faut placer Dsuz entre guillemets :
Maxime Deniaux a écrit :

Code : Tout sélectionner

mutate( Sp = case_when(Sp == "Dsuz_m" ~ Dsuz,
                       Sp == "Dsuz_f" ~ Dsuz
                      ))


Je le remplacerai par :

Code : Tout sélectionner

mutate( Sp = case_when(Sp == "Dsuz_m" ~ "Dsuz",
                       Sp == "Dsuz_f" ~ "Dsuz",
                       TRUE ~ Sp # pour les autres cas de figure
                      ))


Maxime Deniaux a écrit :

Code : Tout sélectionner

data$Sp[data$Sp == "Dsuz_m"] = Dsuz
data$Sp[data$Sp == "Dsuz_f"] = Dsuz


Le mutate tel qu'utilisé dans le code que j'ai proposé permet de ne pas modifier la structure du tableau initial.
Si ça ne pose pas de problèmes pour la suite alors oui tu peux modifier le tableau avant de te lancer dans le group_by et le summarise.
Par contre plutôt que d'aller chercher toutes les combinaisons une à une, tu peux le faire en une seule fois :

Code : Tout sélectionner

data$Sp[data$Sp  %in% c("Dsuz_m", "Dsuz_f")] <- "Dsuz"
# équivalent à
dta$Sp[grep("^Dsuz", dta$Sp)] <- "Dsuz" # basé aussi sur les expressions régulières

Le "%in%" peut aussi s'intégrer dans le case_when tout comme le grepl au besoin.

Code : Tout sélectionner

mutate( Sp = case_when(Sp %in% c("Dsuz_m", "Dsuz_f") ~ "Dsuz",
                       TRUE ~ Sp # pour les autres cas de figure
                      )) # ou
mutate(Sp = case_when(grepl("Dsuz", Sp) ~ "Dsuz",
    TRUE ~ Sp # pour les autres cas de figure
    ))


De manière générale, il est recommandé d'utiliser le "=" pour passer des valeurs à des arguments dans les fonctions et d'utiliser "<-" pour assigner des valeurs à des objets.

Maxime Deniaux a écrit :Concernant group_by_at(), je ne connais pas. Je ne connais que group_by(), j'imagine que si tu mets group_by(Bloc,Trap,Rep,Session,Date_in,Date_out,Sp), tu auras le même résultat.
(group_by() te permet de grouper des variables pour faire des opérations dessus).

Le group_by_at a la même finalité que le group_by, mais au lieu de lui passer le nom des colonnes qui te servent pour regrouper tes données tu lui passes le numéro des colonnes.

Bien cordialement,
Maxime

Maxime Deniaux
Messages : 70
Enregistré le : 11 Fév 2022, 22:49
Contact :

Re: Somme d'une colonne selon les modalités d'un facteur

Messagepar Maxime Deniaux » 19 Déc 2022, 20:48

Je pense que le code suivant est incomplet et qu'il faut placer Dsuz entre guillemets :


Oui, effectivement ! Petite coquille :)

(idem dans
data$Sp[data$Sp == "Dsuz_m"] = Dsuz
)

Merci pour les autres explications

Bonne fin de soirée

Romain Georges
Messages : 3
Enregistré le : 15 Déc 2022, 07:21

Re: Somme d'une colonne selon les modalités d'un facteur

Messagepar Romain Georges » 20 Déc 2022, 07:08

Merci pour vos explications à tous les deux, c'est beaucoup plus clair !

Je crois qu'une de mes difficultés avec R vient du fait qu'il y a toujours plusieurs méthodes pour obtenir le même résultat. Par contre, merci Maxime, j'ai enfin compris pourquoi sur le forum on utilise toujours "<-" pour stocker dans un objet alors que j'avais appris avec le "=".

Bonne journée et au plaisir de vous relire
Romain


Retourner vers « Questions en cours »

Qui est en ligne

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