Regroupement données appariées selon une modalité

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

Thomas Crouchet
Messages : 5
Enregistré le : 14 Mar 2021, 18:22

Regroupement données appariées selon une modalité

Messagepar Thomas Crouchet » 15 Mar 2021, 12:51

Bonjour à tous,

Je dispose d'un jeu de données avec des mesures répétées d'individus pour plusieurs variables :

Code : Tout sélectionner

        ID        Cat Site        Day     Hour Sex Tarsus
1  8384928 Background   AT 20/01/2020 11:14:33   F  21,85
2  8384928     2_GT_M   AT 20/01/2020 11:27:26   F  21,85
3  8384928       1_BT   AT 20/01/2020 15:32:03   F  21,85
4  8384928 Background   AT 21/01/2020 09:44:13   F  21,85
5  8384928 Background   AT 21/01/2020 09:44:16   F  21,85
6  8384928 Background   AT 21/01/2020 09:44:24   F  21,85
7  8384928 Background   AT 21/01/2020 10:12:36   F  21,85
8  8384931     2_GT_M   AT 20/01/2020 14:13:53   M  22,10
9  8384931 Background   AT 20/01/2020 14:31:00   M  22,10
10 8384931     2_GT_M   AT 21/01/2020 11:34:48   M  22,10
11 8384931     2_GT_M   AT 21/01/2020 13:16:59   M  22,10
12 8384931     2_GT_M   AT 21/01/2020 13:17:15   M  22,10
13 8384931       1_BT   AT 21/01/2020 13:17:20   M  22,10
14 8384931     1_GT_F   AT 21/01/2020 15:22:30   M  22,10
15 8384931     1_GT_F   AT 21/01/2020 15:50:02   M  22,10
16 8384933 Background   AU 19/01/2020 11:02:28   F  21,40
17 8384933     1_GT_F   AU 19/01/2020 13:43:50   F  21,40
18 8384933     2_GT_M   AU 19/01/2020 14:42:44   F  21,40
19 8384933     2_GT_M   AU 19/01/2020 14:42:47   F  21,40
20 8384933       1_BT   AU 20/01/2020 14:42:19   F  21,40
21 8384933     2_GT_M   AU 21/01/2020 11:43:19   F  21,40
22 8384933     2_GT_M   AU 21/01/2020 11:43:22   F  21,40
23 8384933 Background   AU 21/01/2020 13:09:15   F  21,40
24 8384933 Background   AU 21/01/2020 13:09:18   F  21,40


Dont le contenu est :

Code : Tout sélectionner

db <- structure(list(ID = c(8384928L, 8384928L, 8384928L, 8384928L,
                            8384928L, 8384928L, 8384928L, 8384931L, 8384931L, 8384931L, 8384931L,
                            8384931L, 8384931L, 8384931L, 8384931L, 8384933L, 8384933L, 8384933L,
                            8384933L, 8384933L, 8384933L, 8384933L, 8384933L, 8384933L),
                     Cat = c("Background", "2_GT_M", "1_BT", "Background", "Background",
                             "Background", "Background", "2_GT_M", "Background", "2_GT_M",
                             "2_GT_M", "2_GT_M", "1_BT", "1_GT_F", "1_GT_F", "Background",
                             "1_GT_F", "2_GT_M", "2_GT_M", "1_BT", "2_GT_M", "2_GT_M",
                             "Background", "Background"), Site = c("AT", "AT", "AT", "AT",
                                                                   "AT", "AT", "AT", "AT", "AT", "AT", "AT", "AT", "AT", "AT",
                                                                   "AT", "AU", "AU", "AU", "AU", "AU", "AU", "AU", "AU", "AU"
                             ), Day = c("20/01/2020", "20/01/2020", "20/01/2020", "21/01/2020",
                                        "21/01/2020", "21/01/2020", "21/01/2020", "20/01/2020", "20/01/2020",
                                        "21/01/2020", "21/01/2020", "21/01/2020", "21/01/2020", "21/01/2020",
                                        "21/01/2020", "19/01/2020", "19/01/2020", "19/01/2020", "19/01/2020",
                                        "20/01/2020", "21/01/2020", "21/01/2020", "21/01/2020", "21/01/2020"
                             ), Hour = c("11:14:33", "11:27:26", "15:32:03", "09:44:13",
                                         "09:44:16", "09:44:24", "10:12:36", "14:13:53", "14:31:00",
                                         "11:34:48", "13:16:59", "13:17:15", "13:17:20", "15:22:30",
                                         "15:50:02", "11:02:28", "13:43:50", "14:42:44", "14:42:47",
                                         "14:42:19", "11:43:19", "11:43:22", "13:09:15", "13:09:18"
                             ), Sex = c("F", "F", "F", "F", "F", "F", "F", "M", "M", "M",
                                        "M", "M", "M", "M", "M", "F", "F", "F", "F", "F", "F", "F",
                                        "F", "F"), Tarsus = c("21,85", "21,85", "21,85", "21,85",
                                                              "21,85", "21,85", "21,85", "22,10", "22,10", "22,10", "22,10",
                                                              "22,10", "22,10", "22,10", "22,10", "21,40", "21,40", "21,40",
                                                              "21,40", "21,40", "21,40", "21,40", "21,40", "21,40")), class = "data.frame", row.names = c(NA,
                                                                                                                                                          -24L))


Je souhaite simplifier ce jeu de données selon les modalités de la variable Cat en faisant :
1) Regroupement des lignes du dataframe avec une ligne par modalité pour chaque individu
2) Pour les variables autres que ID & Cat, recopier les valeurs de la 1ère mesure de chaque modalité pour chaque individu (si modalité absente, indiquer NA)
3) Calcul du nombre de mesures (= nombre de lignes) par modalité pour chaque individu et stockage dans une nouvelle variable

Voici ce que cela pourrait donner avec l'exemple ci-dessus :

Code : Tout sélectionner

        ID        Cat Site        Day     Hour  Sex Tarsus Nb
1  8384928 Background   AT 20/01/2020 11:14:33    F  21,85  5
2  8384928     2_GT_M   AT 20/01/2020 11:27:26    F  21,85  1
3  8384928       1_BT   AT 20/01/2020 15:32:03    F  21,85  1
4  8384928     1_GT_F <NA>       <NA>     <NA> <NA>   <NA>  0
5  8384931 Background   AT 20/01/2020 14:31:00    M  22,10  1
6  8384931     2_GT_M   AT 20/01/2020 14:13:53    M  22,10  4
7  8384931       1_BT   AT 21/01/2020 13:17:20    M  22,10  1
8  8384931     1_GT_F   AT 21/01/2020 15:22:30    M  22,10  2
9  8384933 Background   AU 19/01/2020 11:02:28    F  21,40  3
10 8384933     2_GT_M   AU 19/01/2020 14:42:44    F  21,40  4
11 8384933       1_BT   AU 20/01/2020 14:42:19    F  21,40  1
12 8384933     1_GT_F   AU 19/01/2020 13:43:50    F  21,40  1


4) Dans un deuxième temps (pour d'autres analyses), je souhaite organiser ce nouveau tableau sur le principe d'un tableau de contingence avec :
- 1 ligne = 1 individu
- 1 colonne = 1 modalité de la variable Cat

Voici ce que cela pourrait donner avec l'exemple ci-dessus :

Code : Tout sélectionner

        X Background X2_GT_M X1_BT X1_GT_F
1 8384928          5       1     1       0
2 8384931          1       4     1       2
3 8384933          3       4     1       1



Je ne suis pas très à l'aise avec R et si ma demande me paraît simple en théorie, je ne sais pas si c'est faisable en réalité ! Pour le point 3), j'ai utilisé la fonction table() mais je ne parviens pas à stocker mon résultat dans un nouveau tableau synthétique (point 1 et 2).

Merci d'avance pour vos conseils !!

Thomas

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

Re: Regroupement données appariées selon une modalité

Messagepar Mickael Canouil » 15 Mar 2021, 14:52

Bonjour,

approche data.table :

Code : Tout sélectionner

library("data.table")
dcast(
  data = setDT(db)[= .N, by = c("ID", "Cat")], 
  formula 
= ID ~ Cat, 
  value
.var = "N", 
  fill 
= 0
)
#>         ID 1_BT 1_GT_F 2_GT_M Background
#> 1: 8384928    1      0      1          5
#> 2: 8384931    1      2      4          1
#> 3: 8384933    1      1      4          3    


approche tidyverse (dplyr + tidyr) :

Code : Tout sélectionner

library("dplyr")
library("tidyr")

db %>% 
  count
(ID, Cat) %>% 
  pivot_wider
(id_cols = "ID", names_from = "Cat", values_from = "n", values_fill = 0)
#> # A tibble: 3 x 5
#>        ID `1_BT` `2_GT_M` Background `1_GT_F`
#>     <int>  <int>    <int>      <int>    <int>
#> 1 8384928      1        1          5        0
#> 2 8384931      1        4          1        2
#> 3 8384933      1        4          3        1    


Approche R base :

Code : Tout sélectionner

ag <- aggregate(= db[["ID"]], by = db[c("ID", "Cat")], length)
xtabs(~ ., data = ag)
#>          Cat
#> ID        1_BT 1_GT_F 2_GT_M Background
#>   8384928    1      0      1          5
#>   8384931    1      2      4          1
#>   8384933    1      1      4          3   

Cordialement,
Mickaël
mickael.canouil.fr | rlille.fr

Thomas Crouchet
Messages : 5
Enregistré le : 14 Mar 2021, 18:22

Re: Regroupement données appariées selon une modalité

Messagepar Thomas Crouchet » 15 Mar 2021, 15:43

Merci beaucoup pour cette triple réponse Mickael !!!!
Dans l'approche data.table, quel est l'intérêt de l'argument !is.na(Site) ?

Mon point 4 est donc totalement résolu. Une idée pour obtenir le 1er tableau (point 1 à 3) ?

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

Re: Regroupement données appariées selon une modalité

Messagepar Mickael Canouil » 15 Mar 2021, 15:50

Juste en data.table pour la première partie et sans complétion des données :

Code : Tout sélectionner

library(data.table)
setDT(db)[
  j = list(.N, Day = first(Day), Hour = first(Hour)), 
  by 
= c("ID", "Cat", "Site", "Sex", "Tarsus")
]
#>          ID        Cat Site Sex Tarsus N        Day     Hour
#>  1: 8384928 Background   AT   F  21,85 5 20/01/2020 11:14:33
#>  2: 8384928     2_GT_M   AT   F  21,85 1 20/01/2020 11:27:26
#>  3: 8384928       1_BT   AT   F  21,85 1 20/01/2020 15:32:03
#>  4: 8384931     2_GT_M   AT   M  22,10 4 20/01/2020 14:13:53
#>  5: 8384931 Background   AT   M  22,10 1 20/01/2020 14:31:00
#>  6: 8384931       1_BT   AT   M  22,10 1 21/01/2020 13:17:20
#>  7: 8384931     1_GT_F   AT   M  22,10 2 21/01/2020 15:22:30
#>  8: 8384933 Background   AU   F  21,40 3 19/01/2020 11:02:28
#>  9: 8384933     1_GT_F   AU   F  21,40 1 19/01/2020 13:43:50
#> 10: 8384933     2_GT_M   AU   F  21,40 4 19/01/2020 14:42:44
#> 11: 8384933       1_BT   AU   F  21,40 1 20/01/2020 14:42:19   


J'ai mis à jour, le is.na(Site) ne sert à rien dans le cas présent, simple reliquat d'un essai.
Mickaël
mickael.canouil.fr | rlille.fr

Thomas Crouchet
Messages : 5
Enregistré le : 14 Mar 2021, 18:22

Re: Regroupement données appariées selon une modalité

Messagepar Thomas Crouchet » 15 Mar 2021, 17:54

Merci pour cette piste.

2 questions :
- Dans ce tableau, je voudrais avoir toutes les modalités pour chaque individu. Est-il possible d'intégrer des modalités pour lesquelles je n'ai pas de mesure (sous la forme d'une ligne avec des NA, cf. exemple dans mon 1er post) ?

- Si j'ai bien compris, le by() permet d'indiquer selon quelles variables faire le tri. Dans mon jeu de données complet, j'ai beaucoup plus de variables. Et donc logiquement, si je les indique toutes dans le by(), je me retrouve avec mon tableau de départ avec ces n lignes et non le tableau synthétisé. Une idée pour pouvoir conserver toutes mes variables tout en ayant le tableau synthétique ?

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

Re: Regroupement données appariées selon une modalité

Messagepar Mickael Canouil » 16 Mar 2021, 09:09

Pour le premier point, il y a par exemple tidyr::complete() (https://tidyr.tidyverse.org/reference/complete.html)

Pour le second, il est strictement impossible de réaliser votre point 2, rien qu'au niveau conceptuel, sauf s'il y a des lignes intégralement dupliquées.
Mickaël
mickael.canouil.fr | rlille.fr

Thomas Crouchet
Messages : 5
Enregistré le : 14 Mar 2021, 18:22

Re: Regroupement données appariées selon une modalité

Messagepar Thomas Crouchet » 16 Mar 2021, 09:36

Merci pour l'idée, je vais creuser du côté de tidyr::complete()

Pour le point 2, c'est ce que je craignais. J'ai tenté de m'inspirer de votre solution en ajoutant les autres variables dans le j :

Code : Tout sélectionner

setDT(db)[
  j = list(.N, Day = first(Day), Hour = first(Hour), Tarsus = first(Tarsus), Site = first(Site), Sex = first(Sex)),
  by = c("ID","Cat")
]


Peut être pas très "propre" mais ça a l'air de fonctionner.

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

Re: Regroupement données appariées selon une modalité

Messagepar Mickael Canouil » 16 Mar 2021, 10:14

Vous pouvez ajouter autant de variable que vous voulez dans l'argument {by}, mais ajoutez la totalité des colonnes revient à simplement gérer les lignes dupliquées et dans ce cas cas, il y a des fonctions pour ça duplicated() (en R base ou data.table) par exemple.
L'argument {j} correspond à la gestion des colonnes, vous voulez "calculer" autant de variable que vous voulez (et sur la base du regroupement par {by}).
Mickaël
mickael.canouil.fr | rlille.fr

Thomas Crouchet
Messages : 5
Enregistré le : 14 Mar 2021, 18:22

Re: Regroupement données appariées selon une modalité

Messagepar Thomas Crouchet » 17 Mar 2021, 09:30

Merci pour ces précisions.
Je n'avais pas pensé à duplicated()... super idée !!

Mon problème est résolu.


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité