IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

R Discussion :

Application d'une fonction sur une variable d'un tibble sans perte de performance


Sujet :

R

  1. #1
    Membre expérimenté
    Homme Profil pro
    Attaché statisticien
    Inscrit en
    Mai 2011
    Messages
    687
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Attaché statisticien
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mai 2011
    Messages : 687
    Points : 1 581
    Points
    1 581
    Par défaut Application d'une fonction sur une variable d'un tibble sans perte de performance
    Bonjour,

    je suis passé depuis quelques temps à R, et j'ai sans doute encore un peu de mal avec les fondamentaux du langage.

    J'ai une grosse table à valider, et je veux appliquer une fonction que j'ai créé par ailleurs pour vérifier certaines colonnes.
    La fonction que j'utilise ici n'est qu'un exemple.

    Je créé une table

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    library(dplyr)
    random  <- tibble(     a=sample(1:1000,500000,replace=TRUE),
                          datenaissance=sample(c('20181201','20190505','20180603','20200000'),500000,replace=TRUE)
    )

    Je créé ma function "complexe"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
     
    valide_date <- function(date_a_valider) {
      dtt = as.Date(as.character(date_a_valider),format="%Y%m%d")
     
      if (is.na(dtt))          {
        result="Date incorrecte"
      } else  {
        result="Date correcte"
      }
    }

    et je cherche naïvement à appliquer la fonction à une colonne du tibble.

    DCT1 <- random %>% mutate(test8=valide_date(datenaissance))mais bon ce n'est pas si simple



    > DCT1 <- random %>% mutate(test8=valide_date(datenaissance))
    Warning message:
    Problem with `mutate()` column `test8`.
    ℹ `test8 = valide_date(datenaissance)`.
    ℹ the condition has length > 1 and only the first element will be used
    >



    Bon je commence à chercher et je trouve bien deux solutions

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    # avec Vectorize() 
    valide_datev <- Vectorize(valide_date, vectorize.args = "date_a_valider")
     
     
     
    start_time <- Sys.time()
    DCT1 <- random %>% mutate(test8=valide_datev(datenaissance))
    end_time <- Sys.time()
    dif1=end_time-start_time
     
     
    # avec map_chr() 
    start_time <- Sys.time()
    DCT2 <- random %>% mutate(test8=map_chr(datenaissance,valide_date))
    end_time <- Sys.time()
    dif2=end_time-start_time

    Néanmoins en testant "en dehors" de ma fonction , on voit bien que ces deux solutions ne sont que des pis-aller et il doit certainement avoir une autre façon de faire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    start_time <- Sys.time()
    DCT3 <- random %>% mutate(test8=ifelse(is.na(as.Date(as.character(datenaissance),format="%Y%m%d")),"Date incorrecte","Date correcte"))
    end_time <- Sys.time()
    dif3=end_time-start_time
     
     
     
     
    dif1 # Vectorize()
    dif2  # map_chr()
    dif3 # en dehors de la fonction



    >
    > dif1 # Vectorize()
    Time difference of 47.44273 secs
    > dif2 # map_chr()
    Time difference of 46.01426 secs
    > dif3 # en dehors de la fonction
    Time difference of 0.4939759 secs
    >



    Bref il y a clairement un problème de performance à appliquer la fonction comme je le fait. Mais je n'arrive pas à trouver d'autres écritures plus performantes

    Si vous avez des idées.

    Merci.

  2. #2
    Membre du Club
    Femme Profil pro
    Chef d'entreprise
    Inscrit en
    Juin 2020
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Chef d'entreprise

    Informations forums :
    Inscription : Juin 2020
    Messages : 27
    Points : 40
    Points
    40
    Par défaut
    si vous utilisez des fonctions custom il faut chercher du côté de la programmation fonctionnelle avec purrr et bien comprendre la vectorisation native de R.

    Vous pouvez insérer votre `ifelse()`directement à la suite de votre mutate dans votre chaine dplyr :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    random %>% mutate(test = ifelse(test, sivrai, sinon))
    qui peut parfaitement se combiner avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    random %>% mutate(test = as.Date(as.character(date_a_valider),format="%Y%m%d"), 
    test = ifelse(test, sivrai, sinon))
    Je vous invite à utiliser {readr} pour les imports car les fonctions d'imports détectent les formats date d'emblée.

    Bon courage

  3. #3
    Membre expérimenté
    Homme Profil pro
    Attaché statisticien
    Inscrit en
    Mai 2011
    Messages
    687
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Attaché statisticien
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mai 2011
    Messages : 687
    Points : 1 581
    Points
    1 581
    Par défaut
    Merci effectivement je cherche à utiliser des fonctions utilisateur, c'est un peu l'intérêt d'un langage de programmation d'y définir ses propres fonctions utilisateur.
    J'ai bien vu le ifelse mais si la fonction devient un peu trop compliqué le code va vite devenir imbuvable j'imagine avec toutes ces intrication de ( et )... Je m'attendais à avoir quelque chose dans la philosophie de dplyr...

    Merci de me donner une piste, je vais donc aller voir du côté de purrr.

  4. #4
    Membre du Club
    Femme Profil pro
    Chef d'entreprise
    Inscrit en
    Juin 2020
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Chef d'entreprise

    Informations forums :
    Inscription : Juin 2020
    Messages : 27
    Points : 40
    Points
    40
    Par défaut
    `case_when()` devrait répondre à 80% des besoins et ce de façon plus safe que `ifelse()` dans ce cas

Discussions similaires

  1. Intégrer une fonction sur 4 variables et plus
    Par Blablatoux dans le forum MATLAB
    Réponses: 1
    Dernier message: 06/08/2014, 13h21
  2. Réponses: 2
    Dernier message: 29/04/2014, 17h12
  3. Récupérer une variable PHP dans JS sans la voir dans le code source
    Par lofo7 dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 06/02/2014, 20h46
  4. Récupérer une variable passée par URL sans $_GET
    Par azou_gold dans le forum Langage
    Réponses: 3
    Dernier message: 16/09/2008, 12h09
  5. [Configuration] php pour recuperer une variable dans l'url sans utiliser $_GET
    Par mikebranque dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 22/06/2006, 20h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo