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 :

problème avec apply et pull dans une fonction


Sujet :

R

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Homme Profil pro
    Attaché statisticien
    Inscrit en
    Mai 2011
    Messages
    687
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Mai 2011
    Messages : 687
    Par défaut problème avec apply et pull dans une fonction
    Bonjour,

    je voulais appliquer à une fonction le même schéma de traitement que celui ci-dessous

    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
    18
    19
    20
    21
    l1<- c(1,2,3)
    l2<- c(5,6,7)
    l3<-c(10,11,12)
    tableau <- tibble(l1,l2,l3)
     
    test <- function(donnees)
    {
      t <-sum(donnees)
      return(t)
    }
     
     
    res= c(
      test(tableau[,1]),
      test(tableau[,2]),
      test(tableau[,3])
     
     
    )
     
    apply(tableau,2,test)

    Ici res donne le même résultat que l'apply final

    cependant avec une fonction plus compexe et d'autres données, j'obtiens une erreur que je n'arrive pas à fixer avec une erreur sur la fonction pull que je n'arrive pas à cerner.

    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
    18
    19
    20
    l1<- c("01","02","03")
    l2<- c("10","020","030")
    l3<-c('xx','rr','tt')
    tableau <- tibble(l1,l2,l3)
     
    modalite_correcte=c("01","02","03","tt")
     
    test <- function(donnees,modalite_reference=modalite_correcte)
    {
      t <- dplyr::pull(donnees) %in% modalite_reference
    return(sum(t))
      }
     
    res= c(
            test(tableau[,1]),
            test(tableau[,2]),
            test(tableau[,3])
            )
     
    apply(tableau,2,test)

    Error in UseMethod("pull") : no applicable method for 'pull' applied to an object of classe "character"
    Je dois louper quelque chose de gros, R débutant, je pense que c'est une notion d'objet ou quelque chose comme ça que je loupe.

    Si vous pouviez m'indiquer des pistes...

    Merci

  2. #2
    Membre confirmé
    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
    Par défaut
    pull() est une fonction qui sert à retourner une colonne d'un jeu de données (data.frame ou tibble) sous forme de vecteur.

    Pouvez-vous nous expliquer ce que vous cherchez à faire plutôt que comment vous voulez le faire ?

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

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

    Informations forums :
    Inscription : Mai 2011
    Messages : 687
    Par défaut
    Bonjour et merci.

    Je viens de l'univers SAS, alors je raisonne en observations et variables, pas en lignes, colonnes ni vecteurs.
    C'est sans doute ça qui me joue encore des tours.

    J'ai des tables sous formes de lignes et colonnes (qui sont des imports excel, mais ce n'est pas le soucis) et je veux savoir dans quelle "colonne" est située la variable département. La variable département étant connue, à partir d'une liste licite de modalité de type département ("01","02","03",....."974") je veux savoir combien chaque colonne contient de modalités compatibles avec une variable de type département. Une fois cela fait, en regardant la colonne qui le plus dans ses composantes de modalités compatibles avec une variable département je pourrais repérer automatiquement (en croisant les doigts) ma colonne "departement". Et je pourrais continuer la suite des traitements.

    En lisant attentivement votre réponse, et pris d'un doute, je suis aller regarder la fonction apply. La documentation semble dire qu'apply prends les colonnes pour les mettre dans des vecteurs, du coup je me suis dis que dans ce cas le pull était de trop avec un apply.

    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    library(dplyr)
    l1<- c("01","02","03")
    l2<- c("10","020","030")
    l3<-c('xx','rr','tt')
    tableau <- tibble(l1,l2,l3)
     
     
    modalite_correcte=c("01","02","03","tt")
     
     
    test <- function(donnees,modalite_reference=modalite_correcte)
    {
      t <- donnees %in% modalite_reference
      return(sum(t))
    }
     
     
    res= c(
      test(tableau[,1]),
      test(tableau[,2]),
      test(tableau[,3])
    )
     
     
    apply(tableau,2,test)
    Et effectivement ce code résout mon problème de calcul.


    Mais il fait émerger une seconde question subsidiaire.
    Avec mon tibble de départ, et ma fonction de départ (avec le pull). Comment faire la même chose que le apply ?

    Car en effet sans le pull , le résultat de apply(tableau,2,test) est sans erreur et correct, mais le code au dessus pour vérifier qu'on obtientbien la même chose

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    res= c(
      test(tableau[,1]),
      test(tableau[,2]),
      test(tableau[,3])
    )
    ne donne plus le bon résultat. Ce n'est pas grave, mais dans l'idéal, j'aimerais que la fonction puisse marche à la fois dans le apply et aussi dans l'utilisation "simple" tel que je le fait pour la création de res.
    Et ce pourquoi je me pose la question, au final c'est que je n'ai pas tout compris, mais je me demande quelle notion je n'ai pas acquis pour ne pas tomber dans le "piège"...


    En tout cas merci de votre aide

    Jérôme

  4. #4
    Membre Expert
    Inscrit en
    Novembre 2009
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 707
    Par défaut problème dans une fonction
    Bonjour,

    La différence est liée à l'utilisation du tibble. Il n'y a pas de problème avec les dataframes :

    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    l1 <- c("01", "02", "03")
    l2 <- c("10", "020", "030")
    l3 <- c('xx', 'rr', 'tt')
    tableau <- data.frame(l1,l2,l3)
    tableau 
    #>   l1  l2 l3
    #> 1 01  10 xx
    #> 2 02 020 rr
    #> 3 03 030 tt
     
    modalite_correcte=c("01","02","03","tt")
     
    test <- function(donnees,modalite_reference=modalite_correcte)
    {
      t <- donnees %in% modalite_reference
      return(sum(t))
    }
     
    res <- c(
      test(tableau[,1]),
      test(tableau[,2]),
      test(tableau[,3])
    )
    res
    #> [1] 3 0 1
     
    res <- apply(tableau,2,test)
    res
    #> l1 l2 l3 
    #>  3  0  1
     
    # Created on 2020-09-05 by the reprex package (v0.3.0)
    Je vous conseille par ailleurs de créer vos dataframes ou tibbles ligne par ligne, c'est plus lisible :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    tableau <- read.table(header=TRUE, check.names=FALSE, colClasses = "character", text="
    l1  l2 l3
    01  10 xx
    02 020 rr
    03 030 tt
    ")
    Cordialement,

  5. #5
    Membre confirmé
    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
    Par défaut
    SAS et R sont 2 langages de statistiques, leur objet de prédilection est le tableau de données avec en lignes les individus (ou observations) et en colonnes les variables qui décrivent les individus.
    SAS parcourt des lignes quand il s'agit d'itérer.
    R est vectoriel : une instruction de type 1:3 == 1:3 (où l'on teste l'égalité de 2 vecteurs identiques) renvoie TRUE TRUE TRUE car tout est fait élément par élément.
    Tous les éléments d'un vecteur dans R sont du même type : que des chiffres, que du texte etc...impossible de les mélanger.
    (essayez c(TRUE,1, "bonjour") )

    Le tableau de données data.frame est une juxtaposition verticale de vecteurs de même longueur qui constitue ainsi les variables (un tableau de données peut donc mélanger les types). Et il est bien composé d'observations et de variables.

    Quand on sélectionne une seule variable d'un data.frame avec $ ou [] on récupère un vecteur alors que quand on sélectionne une seule variable avec dplyr::select() on récupère un tbl d'une seule colonne (on est toujours dans 2 dimensions avec des individus et une seule variable). pull() est l'instruction qui permet "tirer" une variable d'un data.frame ou d'un tbl sous forme de vecteur (unidimensionnel, ça n'est plus une variable à proprement parlé).

    Vous utilisez la fonction apply. Elle s'applique sur une matrice. Une matrice est un vecteur (tous les éléments du même type) qui est contraint en ligne et en colonnes pour ressembler à un tableau et l'on comprend mieux pourquoi cela ne fait pas sens de parler d'observations et de variables. En appliquant une fonction apply sur un dataframe ou un tbl, on convertit l'objet en matrice à la volée.

    Nous avons publié une série d'articles pour les programmeurs SAS qui voudraient comprendre les équivalents R dans le tidyverse ici : https://thinkr.fr/sas2r-episode-1-pr...ry-proc-means/

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

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

    Informations forums :
    Inscription : Mai 2011
    Messages : 687
    Par défaut
    Merci, je vais essayer de retenir la substantifique moelle de votre réponse. Par contre je ne suis pas trop d'accord sur le fait que R et SAS manipulent des tableaux. R oui. SAS ne connait que l'observation. D'ailleurs c'est pour ça qu'il ne sait rien faire d'autre que lire ligne à ligne, c'est aussi toute sa puissance sur les gros fichiers. Alors bien sûr sauf si on est en SAS IML mais là on est plus dans le langage SAS a proprement parler.


    Je vais essayer d'un peu mieux capter ces concepts R...
    Par contre j'ai utilisé apply par ce que rien d'autre ne me venait à l'idée. Je suis ouvert à d'autre choses.
    Dans l'idéal je cherche juste un truc machin du genre truc_machin(donnees,fonction) qui applique ma fonction aux colonnes de mes données.

    Parce que mes données en sont bien des colonnes, puisqu'il s'agit de colonnes excel, qui n'ont à priori rien à voir avec un tableau de données, mais ont tout de l'onglet excel. Onglet Excel dans lequel je dois essayer de retrouver une structure qui s'apparenterait à un tableau. Lorsqu'on peut faire des mises à disposition en csv pourquoi faire simple ? Mettons ça dans un onglet excel avec titres et sous titre, mise en forme et tout le tatouin !

    Merci en tout cas.

  7. #7
    Membre Expert
    Inscrit en
    Novembre 2009
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 707
    Par défaut apply, sapply, lapply
    Bonjour,

    Vous pouvez remplacer la fonction apply(), par la fonction sapply() :

    Citation Envoyé par faubry Voir le message
    L'utilisation de sapply est plus performante car elle tient compte du fait que les data.frame sont des listes particulières. A noter que la solution avec apply ou celle ci-dessous avec sapply renvoient des matrices de chaines de caractères.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    df2 <- sapply(df, formatage)
    Si tu veux un data.frame de facteurs, la solution est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    df3 <- as.data.frame(lapply(df, formatage))
    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    tableau <- read.table(header=TRUE, check.names=FALSE, colClasses = "character", text="
    l1  l2 l3
    01  10 xx
    02 020 rr
    03 030 tt
    ")
     
    modalite_correcte=c("01","02","03","tt")
     
    test <- function(donnees,modalite_reference=modalite_correcte)
    {
      t <- donnees %in% modalite_reference
      return(sum(t))
    }
     
    res <- c(
      test(tableau[,1]),
      test(tableau[,2]),
      test(tableau[,3])
    )
    res
    #> [1] 3 0 1
     
    res <- sapply(tableau,test)
    res
    #> l1 l2 l3 
    #>  3  0  1
    str(res)
    #>  Named int [1:3] 3 0 1
    #>  - attr(*, "names")= chr [1:3] "l1" "l2" "l3"
     
    res <- as.data.frame(lapply(tableau,test))
    res
    #>   l1 l2 l3
    #> 1  3  0  1
    str(res)
    #> 'data.frame':    1 obs. of  3 variables:
    #>  $ l1: int 3
    #>  $ l2: int 0
    #>  $ l3: int 1
     
    # Created on 2020-09-06 by the reprex package (v0.3.0)
    Cordialement,

Discussions similaires

  1. [MySQL] Problème de récupération des données dans une fonction
    Par highman dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 26/10/2006, 20h04
  2. [SQL] Problème avec nombre d'enregistrements dans une table
    Par zana74 dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 14/08/2006, 13h28
  3. Problème avec nombre d'enregistrements dans une table
    Par zana74 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 14/08/2006, 13h21
  4. [VB6] Problème avec la touche 0 dans une MaskEdBox
    Par bb62 dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 02/03/2006, 09h47
  5. Réponses: 9
    Dernier message: 13/05/2005, 03h13

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