pivot dynamique avec pivot_longer

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

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

pivot dynamique avec pivot_longer

Messagepar Serge Rapenne » 18 Avr 2020, 18:09

Bonjour à tous,

Je voudrais pouvoir effectuer une fonction pivot_longer mais ou le paramètre "cols" proviendrait d'une variable chaine (par ex d'un textinput dans shiny) .

par ex :

Code : Tout sélectionner

dta<-data.frame(id=1:5,J1=runif(5),J2=runif(5),D1=runif(5),D2=runif(5))
dta
  id         J1        J2         D1         D2
1  1 0.10470284 0.6718917 0.66825285 0.21345022
2  2 0.80076711 0.1899041 0.37058554 0.82608881
3  3 0.59664031 0.2793409 0.91642900 0.55662805
4  4 0.01927455 0.1037999 0.47330068 0.02240972
5  5 0.92856442 0.5126514 0.03475537 0.21811140
list_col="contains('J')"
dta_long<-dta_long %>% pivot_longer(list_col,names_to = "id_col",values_to = "valeur")

mais bien sur ça ne fonctionne pas (Erreur : Unknown column `contains('J')` )

est il possible de faire çà ?

Merci d'avance pour votre aide

Serge

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

Re: pivot dynamique avec pivot_longer

Messagepar Pierre-Yves Berrard » 18 Avr 2020, 22:14

Bonjour,

Code : Tout sélectionner

# library(dplyr)
# library(tidyr)

motif <- "J"

dta %>%
  pivot_longer(
    grep(motif, names(.), value = TRUE),
    names_to = "id_col",
    values_to = "valeur"
  )

?
PY

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

Re: pivot dynamique avec pivot_longer

Messagepar Serge Rapenne » 18 Avr 2020, 22:29

Merci de ta réponse Pierre-Yves,

c'est un bon début, mais je suis exigent, je voudrais que ça gère aussi les cas du genre

Code : Tout sélectionner

motif<-"-1"
#ou
motif<-"2:4"
#le luxe serait de pouvoir gérer aussi des choses du genre
motif<- "-D1,-D2"

quoi qu'il en soit merci de te pencher sur mon problème

Serge

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

Re: pivot dynamique avec pivot_longer

Messagepar Pierre-Yves Berrard » 18 Avr 2020, 22:40

Ma première idée serait de construire l'instruction complète sous forme de chaîne de caractère, puis de l'eval()uer.

Il faut bien voir qu'on touche ici un des problèmes avec les packages du tidyverse ; il sont très pratiques pour des programmes interactifs, mais difficiles à utiliser quand on veut programmer avec.
PY

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

Re: pivot dynamique avec pivot_longer

Messagepar Pierre-Yves Berrard » 19 Avr 2020, 11:38

Code : Tout sélectionner

library(dplyr)
library(tidyr)
dta <- data.frame(id=1:5,J1=runif(5),J2=runif(5),D1=runif(5),D2=runif(5))

Code : Tout sélectionner

pivot_dta <- function(cols_chr) {
  pivot_chr <-
    sprintf(
      "pivot_longer(
         data = dta,
         cols = %s,
         names_to = \"id_col\",
         values_to = \"valeur\"
       )",
       cols_chr
    )
  eval(parse(text = pivot_chr))
}

Code : Tout sélectionner

pivot_dta("contains(\"J\")")
pivot_dta("-1")
pivot_dta("2:4")
# pivot_dta("-D1, -D2")
(le dernier ne marche pas tout court, même avec un appel direct)
PY

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

Re: pivot dynamique avec pivot_longer

Messagepar Mickael Canouil » 20 Avr 2020, 08:19

Bonjour,

la dernière instruction fonctionne à condition de respecter le type de l'argument "cols", à savoir un vecteur ou le résultat de l'un des "helpers" de dplyr (contains, matches, ...)

Code : Tout sélectionner

pivot_dta("-c(D1, D2)"

Cordialement,

PS: le "mono pipe" c'est moche ;p

EDIT : avec un peu de "tidy eval"

Code : Tout sélectionner

library("tidyr")
library("rlang")
dta <- data.frame(id=1:5,J1=runif(5),J2=runif(5),D1=runif(5),D2=runif(5))
pivot_dta <- function(.datacols) {
  
pivot_longer(
    
data = .data,
    
cols = !!enquo(cols),
    
names_to "id_col",
    
values_to "valeur"
  
)

Code : Tout sélectionner

pivot_dta(dtacontains("J"))
#> # A tibble: 10 x 5
#>       id    D1     D2 id_col valeur
#>    <int> <dbl>  <dbl> <chr>   <dbl>
#>  1     1 0.998 0.255  J1      0.215
#>  2     1 0.998 0.255  J2      0.951
#>  3     2 0.452 0.0112 J1      0.548
#>  4     2 0.452 0.0112 J2      0.569
#>  5     3 0.825 0.119  J1      0.407
#>  6     3 0.825 0.119  J2      0.884
#>  7     4 0.779 0.578  J1      0.389
#>  8     4 0.779 0.578  J2      0.433
#>  9     5 0.166 0.633  J1      0.181
#> 10     5 0.166 0.633  J2      0.813 

Code : Tout sélectionner

pivot_dta(dta, -1)
#> # A tibble: 20 x 3
#>       id id_col valeur
#>    <int> <chr>   <dbl>
#>  1     1 J1     0.215 
#>  2     1 J2     0.951 
#>  3     1 D1     0.998 
#>  4     1 D2     0.255 
#>  5     2 J1     0.548 
#>  6     2 J2     0.569 
#>  7     2 D1     0.452 
#>  8     2 D2     0.0112
#>  9     3 J1     0.407 
#> 10     3 J2     0.884 
#> 11     3 D1     0.825 
#> 12     3 D2     0.119 
#> 13     4 J1     0.389 
#> 14     4 J2     0.433 
#> 15     4 D1     0.779 
#> 16     4 D2     0.578 
#> 17     5 J1     0.181 
#> 18     5 J2     0.813 
#> 19     5 D1     0.166 
#> 20     5 D2     0.633 

Code : Tout sélectionner

pivot_dta(dta2:4)
#> # A tibble: 15 x 4
#>       id     D2 id_col valeur
#>    <int>  <dbl> <chr>   <dbl>
#>  1     1 0.255  J1      0.215
#>  2     1 0.255  J2      0.951
#>  3     1 0.255  D1      0.998
#>  4     2 0.0112 J1      0.548
#>  5     2 0.0112 J2      0.569
#>  6     2 0.0112 D1      0.452
#>  7     3 0.119  J1      0.407
#>  8     3 0.119  J2      0.884
#>  9     3 0.119  D1      0.825
#> 10     4 0.578  J1      0.389
#> 11     4 0.578  J2      0.433
#> 12     4 0.578  D1      0.779
#> 13     5 0.633  J1      0.181
#> 14     5 0.633  J2      0.813
#> 15     5 0.633  D1      0.166 

Code : Tout sélectionner

pivot_dta(dtac(-D1, -D2))
#> # A tibble: 15 x 4
#>       D1     D2 id_col valeur
#>    <dbl>  <dbl> <chr>   <dbl>
#>  1 0.998 0.255  id      1    
#>  2 0.998 0.255  J1      0.215
#>  3 0.998 0.255  J2      0.951
#>  4 0.452 0.0112 id      2    
#>  5 0.452 0.0112 J1      0.548
#>  6 0.452 0.0112 J2      0.569
#>  7 0.825 0.119  id      3    
#>  8 0.825 0.119  J1      0.407
#>  9 0.825 0.119  J2      0.884
#> 10 0.779 0.578  id      4    
#> 11 0.779 0.578  J1      0.389
#> 12 0.779 0.578  J2      0.433
#> 13 0.166 0.633  id      5    
#> 14 0.166 0.633  J1      0.181
#> 15 0.166 0.633  J2      0.813 
Mickaël
mickael.canouil.fr | rlille.fr

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

Re: pivot dynamique avec pivot_longer

Messagepar Serge Rapenne » 20 Avr 2020, 11:11

un grand merci à vous deux, c'est nickel

PS: le "mono pipe" c'est moche ;p

Je l'attendais celle là :-)

Serge


Retourner vers « Questions en cours »

Qui est en ligne

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