Utilisation de pivot_longer()/wider()

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

Fred Santos
Messages : 233
Enregistré le : 11 Avr 2009, 10:00
Contact :

Utilisation de pivot_longer()/wider()

Messagepar Fred Santos » 10 Mar 2022, 11:38

Salut à tous,

Une question d'optimisation de code "juste par curiosité". Voici un exemple de dataframe :

Code : Tout sélectionner

dat <- structure(list(Ind = structure(1:6, .Label = c("C002", "C007", 
"C009", "C010", "C013", "C016"), class = "factor"), Sex = structure(c(1L, 
1L
, 1L, 1L, 1L, 1L), .Label = "F", class = "factor"), DCOX_L = c(213L, 
197L
, 205L, 204L, 202L, 197L), DCOX_R = c(213L, 197L, 200L, 203L, 
202L
, 193L), IIMT_L = c(43L, 48L, 37L, 53L, 61L, 47L), IIMT_R = c(43L, 
50L
, 36L, 52L, 55L, 45L), ISMM_L = c(105L, 95L, 96L, 104L, 97L, 
97L
), ISMM_R = c(107L, 95L, 99L, 105L, 98L, 98L)), row.names = c(NA, 
6L
), class = "data.frame")
print(
dat)

#>    Ind Sex DCOX_L DCOX_R IIMT_L IIMT_R ISMM_L ISMM_R
#> 1 C002   F    213    213     43     43    105    107
#> 2 C007   F    197    197     48     50     95     95
#> 3 C009   F    205    200     37     36     96     99
#> 4 C010   F    204    203     53     52    104    105
#> 5 C013   F    202    202     61     55     97     98
#> 6 C016   F    197    193     47     45     97     98       

En gros, j'ai donc un identifiant d'individu (Ind), puis quelques mesures osseuses (DCOX, IIMT, ISMM) qui sont prises des deux côtés du corps (Left, Right). Le but serait de pivoter ce dataframe le plus simplement possible pour obtenir ceci :

Code : Tout sélectionner

#>    Ind   Sex   side   DCOX  IIMT  ISMM
#>  1 C002  F     L       213    43   105
#>  2 C002  F     R       213    43   107
#>  3 C007  F     L       197    48    95
#>  4 C007  F     R       197    50    95
#>  5 C009  F     L       205    37    96
#>  6 C009  F     R       200    36    99
#>  7 C010  F     L       204    53   104
#>  8 C010  F     R       203    52   105
#>  9 C013  F     L       202    61    97
#> 10 C013  F     R       202    55    98
#> 11 C016  F     L       197    47    97
#> 12 C016  F     R       193    45    98

J'y parviens en utilisant successivement pivot_longer() puis pivot_wider(), de la manière suivante :

Code : Tout sélectionner

library(tidyverse)
dat |>
    pivot_longer(cols = DCOX_L:ISMM_R, names_to = c("var", "side"), names_pattern = "([[:alnum:]]*)_([LR]*)") |>
    pivot_wider(names_from = "var", values_from = "value")

Même si ça semble être une stratégie classique à en croire la doc de {tidyr}, je me demande confusément s'il n'y aurait pas moyen de faire ça encore plus simplement en n'utilisant que pivot_longer(). Verriez-vous une façon plus efficace/élégante de procéder que ce que j'ai fait ici ?

Merci !

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

Re: Utilisation de pivot_longer()/wider()

Messagepar Logez Maxime » 10 Mar 2022, 13:07

Bonjour,

de base tu peux faire :

Code : Tout sélectionner

reshape(dat, direction = "long", varying = 3:8, sep = "_")
# et pour complexifier :
dat %>% gather("var", "value", -(1:2)) %>% 
  separate
(var, into = c("var", "side")) %>% 
  pivot_wider
(names_from=var, values_from=value)
Cordialement,
Maxime

Fred Santos
Messages : 233
Enregistré le : 11 Avr 2009, 10:00
Contact :

Re: Utilisation de pivot_longer()/wider()

Messagepar Fred Santos » 10 Mar 2022, 13:17

Salut Maxime,
Ah oui bigre, il y avait en effet vraiment plus simple ! (Et en R base :-))
Merci beaucoup pour l'astuce !

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

Re: Utilisation de pivot_longer()/wider()

Messagepar Mickael Canouil » 11 Mar 2022, 15:52

Euh, on se le fait en une fonction, même avec tidyr::pivot_longer ^^

Code : Tout sélectionner

dat <- structure(list(Ind structure(1:6, .Label c("C002""C007"
"C009""C010""C013""C016"), class = "factor"), Sex structure(c(1L
1L1L1L1L1L), .Label "F", class = "factor"), DCOX_L c(213L
197L205L204L202L197L), DCOX_R c(213L197L200L203L
202L193L), IIMT_L c(43L48L37L53L61L47L), IIMT_R c(43L
50L36L52L55L45L), ISMM_L c(105L95L96L104L97L
97L), ISMM_R c(107L95L99L105L98L98L)), row.names c(NA
6L), class = "data.frame"

Code : Tout sélectionner

tidyr::pivot_longer(
  
data dat,
  
cols = -c("Ind""Sex"),
  
names_pattern "(.*)_(.*)",
  
names_to c(".value""side")
)
#> # A tibble: 12 × 6
#>    Ind   Sex   side   DCOX  IIMT  ISMM
#>    <fct> <fct> <chr> <int> <int> <int>
#>  1 C002  F     L       213    43   105
#>  2 C002  F     R       213    43   107
#>  3 C007  F     L       197    48    95
#>  4 C007  F     R       197    50    95
#>  5 C009  F     L       205    37    96
#>  6 C009  F     R       200    36    99
#>  7 C010  F     L       204    53   104
#>  8 C010  F     R       203    52   105
#>  9 C013  F     L       202    61    97
#> 10 C013  F     R       202    55    98
#> 11 C016  F     L       197    47    97
#> 12 C016  F     R       193    45    98 
Mickaël
mickael.canouil.fr | rlille.fr

Fred Santos
Messages : 233
Enregistré le : 11 Avr 2009, 10:00
Contact :

Re: Utilisation de pivot_longer()/wider()

Messagepar Fred Santos » 11 Mar 2022, 16:01

Aaaaaah, merci Mickaël ! J'avais pas vu ce passage-là dans la doc :

Code : Tout sélectionner

".value" indicates that the corresponding component of the column name defines the name of the output column containing the cell values, overriding values_to entirely.

Merci à vous tous ;-)

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

Re: Utilisation de pivot_longer()/wider()

Messagepar Logez Maxime » 14 Mar 2022, 08:07

Bonjour,

C'est cool je ne connaissais pas non plus et je trouvais ça dommage qu'on ne puisse pas le faire simplement avec ce genre de fonction.
J'aime beaucoup tidyverse, par contre je trouve parfois dommage que ces fonctions ne soient pas plus performantes.
Quand on recherche l'efficacité, il est parfois plus intéressant de rester sur les fonctions de base, au détriment de la lisibilité, facilité d'utilisation.

Cordialement,
Maxime

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

Re: Utilisation de pivot_longer()/wider()

Messagepar Mickael Canouil » 14 Mar 2022, 08:44

En terme d'efficacité, perso je suis pasé du {tidyverse} à {data.table}.
En plus des performances, il y a moins de dépendances (même s'il n'y a pas trop de soucis à se faire du côté du maintien du tidyverse).
Mickaël
mickael.canouil.fr | rlille.fr


Retourner vers « Questions en cours »

Qui est en ligne

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