Prise en charge d'un tableau dans une fonction

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

Xavier Mesmin
Messages : 9
Enregistré le : 12 Fév 2016, 08:02

Prise en charge d'un tableau dans une fonction

Messagepar Xavier Mesmin » 12 Fév 2016, 09:01

Bonjour,

Je suis plutôt débutant dans la création de fonctions sous R, et je rencontre un problème dont j’identifie mal la source.
Je souhaite créer une fonction qui prend en entrée un tableau de données (type data.frame) et 3 chaînes de caractères. La sortie unique est un nouveau tableau de données (toujours de type data.frame), qui correspond à une modification du tableau d’entrée.
Voici la fonction, Tbinomial étant le tableau d'entrée ; Echec, Succès et Varbernoulli étant mes trois chaînes de caractères, qui renvoient dans la fonction à des intitulés de colonne du tableau d'entrée ou de sortie.

Code : Tout sélectionner

Transfobinobernou <- function(Tbinomial, Echec, Succès, Varbernoulli) {
 
  Tbernoulli <- Tbinomial[,-c((ncol(Tbinomial)-1), ncol(Tbinomial))] # Mon nouveau tableau correspond à une troncature du tableau d'entrée. J'enlève les 2 dernières colonnes
  Tbernoulli[(nrow(Tbernoulli) + 1) : (sum(Tbinomial[,Echec]) + sum(Tbinomial[,Succès])),] <- NA # Je rajoute un nombre de lignes précis à ce tableau (dépendant des données Echec et Succès du tableau d'entrée), correspondant à l'extension recherchée du tableau de sortie
  Tbernoulli[,(ncol(Tbernoulli)+1)] <- 2 # Je rajoute une colonne à ce tableau. Ses dimensions sont maintenant correctes
  colnames(Tbernoulli)[ncol(Tbernoulli)] <- Varbernoulli # Je renomme l'intitulé de ma nouvelle variable : mon nouveau tableau est près à être rempli.
 
  j <- 1 # j va parcourir les lignes de mon tableau de sortie
 
  for (i in 1:nrow(Tbernoulli)) { # i parcourt les lignes de mon tableau d'entrée
   
    n1 <- as.numeric(Tbinomial[i, Echec]) # Je récupère le nombre d'échec pour l'expérience binomiale de mon tableau d'entrée
    n2 <- as.numeric(Tbinomial[i, Succès]) # Je récupère le nombre de succès pour l'expérience binomiale de mon tableau d'entrée
   
    if (!(n1 == 0)) {
      Tbernoulli[j : (j+n1-1), Varbernoulli] <- 0 # Je mets autant de 0 dans le tableau de sortie qu'il y a eu d'échec dans l'expérience
    }
   
    if (!(n2 == 0)) {
      Tbernoulli[(j+n1) : (j+n1+n2-1), Varbernoulli] <- 1 # Je mets autant de 1 dans le tableau de sortie qu'il y a eu de succès dans l'expérience
    }
   
    if (!(n1 + n2 == 0)) {
      Tbernoulli[j : (j+n1+n2-1), 1 : (ncol(Tbernoulli)-1)] <- Tbinomial[i, 1 : (ncol(Tbinomial)-2)] # Toutes les données que je viens d'insérer correspondent à la même expérience binomiale. Les autres colonnes sont donc invariantes.
    }
   
    j <- j+n1+n2 # Je reprendrai mon tableau de sortie à l'endroit où j'ai terminé de remplir le tableau
  }
  return(Tbernoulli)
}


Le chargement de la fonction ne pose aucun problème. C’est lorsque je l’utilise avec des données réelles en entrée que j’obtiens un message d’erreur.

R me donne une erreur au moment du test logique ( !(n1 == 0)) au début de la boucle for, il me dit qu’il n’a ni TRUE ni FALSE. Probablement, la comparaison que je lui demande de faire n’a pas de sens lors de l’exécution de la fonction, il doit tomber sur NA. J’en ai déduit :
- que n1 et n2 qui sont calculés au début de ma boucle for ne doivent pas être numérique (sinon la comparaison devrait pouvoir se faire)
- que donc, probablement, mon tableau d’entrée Tbinomial n’est pas reconnu comme un data.frame à l’intérieur de ma fonction. Si tel est le cas je ne vois pas comment faire…
Merci d’avance pour votre aide.

PS : Vous aurez peut-être saisi que je cherche ici à transformer un tableau contenant une variable binomiale (nombre de succès en n expériences de Bernoulli indépendantes) et sa variable complémentaire (nombre d’échec) en un tableau contenant la même donnée mais sous forme d’une variable de Bernoulli (une ligne par expérience de Bernoulli). C’est essentiel pour modéliser les variables sous R avec une famille binomiale. Si vous connaissez une fonction déjà écrite qui fait ça, ça m’intéresse aussi !

Florent Aubry
Messages : 324
Enregistré le : 25 Juin 2010, 10:21

Re: Prise en charge d'un tableau dans une fonction

Messagepar Florent Aubry » 12 Fév 2016, 13:50

Le représentation des variables binomiales sous R peut prendre 3 formes qui sont toutes les 3 prises en charge par glm et les autres procédures gérant des données binomiales que je connait :
1) la variable dépendante est un facteur F à deux nivaux, le premier niveau du facteur est le niveau d’intérêt (ou le ‘succès’) ;
2) une variable binaire de valeurs 0 ou 1 (FALSE ou TRUE), avec 0 le niveau d’intérêt (ou le succès) ;
3) la variable dépendante est une matrice à deux colonnes dont chaque ligne est le nombre de succès et d’échecs pour le profil de valeurs des prédicteurs [décompte de de 0 et de 1 du 2) ou de niveaux 1 et 2 du 1] par combinaisons des autres prédicteurs.

Donc, je pense que tu te compliques la vie pour rien.

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

Re: Prise en charge d'un tableau dans une fonction

Messagepar Logez Maxime » 12 Fév 2016, 14:20

Bonjour,

une possibilité :

Code : Tout sélectionner

set.seed(10)
tab <- data.frame(x=rnorm(10), y=rnorm(10), success=rpois(10,2), echec=rpois(10,2))
# en utilisant le package reshape2
tab2 <- melt(tab, id=c("x", "y"))
tab2 <- tab2[rep(1:nrow(tab2), tab2$value),-ncol(tab2)]
tab2$variable  <- (tab2$variable=="success")*1
Cordialement,
Maxime

Xavier Mesmin
Messages : 9
Enregistré le : 12 Fév 2016, 08:02

Re: Prise en charge d'un tableau dans une fonction

Messagepar Xavier Mesmin » 15 Fév 2016, 16:57

Merci beaucoup pour vos réponses rapides!

Concernant la proposition de Maxime pour la programmation de la fonction, ça fonctionne effectivement très bien. Je n'aurais pas trouvé l'astuce tab2[rep(1:nrow(tab2), tab2$value). Reste que je ne comprends pas où la mienne plantait, sachant qu'en plus en prenant le script du corps de fonction sur mon jeu de données cela fonctionnait très bien...

Et en effet, j'ai trouvé de la documentation sur le fonctionnement du glm binomial. On peut passer en entrée une matrice (et pas un data.frame) contenant en 1è colonne le nombre de succès à chaque expérience binomiale et en 2è colonne le nombre d'échecs correspondants. Il est donc en effet inutile de transformer tout le tableau comme j'ai cherché à le faire.

Xavier

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

Re: Prise en charge d'un tableau dans une fonction

Messagepar Logez Maxime » 16 Fév 2016, 09:51

Il est donc en effet inutile de transformer tout le tableau comme j'ai cherché à le faire.
Pas tout à fait. Les estimations de la vraisemblance et donc de la déviance ne sont pas les mêmes selon le format de données :

Code : Tout sélectionner

glm1 <- glm(cbind(success, echec) ~ x, data=tab, family=binomial())
glm1

Call:  glm(formula = cbind(success, echec) ~ x, family = binomial(),
    data = tab)

Coefficients:
(Intercept)            x 
    -0.1476       0.8077 

Degrees of Freedom: 9 Total (i.e. Null);  8 Residual
Null Deviance:      7.007
Residual Deviance: 5.963        AIC: 22.35

glm2 <- glm(variable ~ x, data=tab2, family=binomial())
glm2

Call:  glm(formula = variable ~ x, family = binomial(), data = tab2)

Coefficients:
(Intercept)            x 
    -0.1476       0.8077 

Degrees of Freedom: 29 Total (i.e. Null);  28 Residual
Null Deviance:      40.38
Residual Deviance: 39.34        AIC: 43.34
Cordialement,
Maxime

Xavier Mesmin
Messages : 9
Enregistré le : 12 Fév 2016, 08:02

Re: Prise en charge d'un tableau dans une fonction

Messagepar Xavier Mesmin » 09 Fév 2017, 15:19

Merci pour cette réponse complémentaire que je note bien tardivement!


Retourner vers « Questions en cours »

Qui est en ligne

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

cron