Lattice : passage des données à la fonction panel()

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

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Lattice : passage des données à la fonction panel()

Messagepar François Bonnot » 04 Avr 2017, 09:42

Bonjour,
Soit le data frame suivant:

Code : Tout sélectionner

df <- expand.grid(x=1:3,y=1:4,g=factor(1:4))
df$letter <- sample(LETTERS,nrow(df),replace=TRUE)

Pour afficher la lettre en position (x,y) pour chaque groupe avec le package lattice, on peut utiliser la syntaxe suivante:

Code : Tout sélectionner

library(lattice)
xyplot(y~x|g,data=df,
       panel=function(x,y,groups,subscripts,...) ltext(x,y,df$letter[subscripts[groups]])
       )

Mais si on remplace la fonction panel() par

Code : Tout sélectionner

panel=function(x,y,groups,subscripts,...) ltext(x,y,letter[subscripts[groups]])

(sans spécifier "df$" avant "letter") alors on obtient l'erreur: Error using packet 1, object 'letter' not found.
Les variables de df ne sont donc pas passées à la fonction panel() (la documentation de xyplot() n'est pas très claire sur ce point).
Ce fonctionnement peut être gênant dans des cas plus complexes où l'on doit utiliser plusieurs variables du data frame, car en cas de changemnt de data frame il faut modifier le code à plusieurs endroits ce qui fait perdre l'intérêt de l'argument data=.
Ma question est la suivante:
Y a-t-il une syntaxe permettant de signaler à panel() qu'on veut utiliser toutes les colonnes du data frame ?
François

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

Re: Lattice : passage des données à la fonction panel()

Messagepar Logez Maxime » 07 Avr 2017, 13:25

Bonjour François,

Désolé je ne vais répondre directement à ta question mais je trouve ça tellement plus simple avec ggplot2 :

Code : Tout sélectionner

ggplot(df, aes(x, y, label = letter)) + geom_text() + facet_wrap(~g)
Cordialement,
Maxime

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Re: Lattice : passage des données à la fonction panel()

Messagepar François Bonnot » 07 Avr 2017, 14:08

Merci Maxime.
ggplot2 semble très puissant mais comme c'est un package supplémentaire à maîtriser en plus de graphics et lattice je n'ai jamais pris le temps de m'y mettre. Il faudra que je l'envisage quand j'en aurai l'occasion.
Cordialement,
François

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

Re: Lattice : passage des données à la fonction panel()

Messagepar Mickael Canouil » 07 Avr 2017, 15:19

Bonjour,

par défaut xyplot (et sa méthode lattice:::xyplot.formula) extrait les arguments à passer dans "panel" via les termes de l'objet "formula", ici x.
Ainsi, sous la forme donnée, les colonnes additionnels de "df" ne peuvent être transmises à la fonction définie dans "panel".

Cependant, tout argument placé dans "...", seront transmis à la fonction dans "panel" à la condition qu'ils existent dans celle-ci.

Code : Tout sélectionner

xyplot(y~x|g, data=df,
    letterArg = df$letter,
    panel=function(x,y,subscripts,groups, letterArg,...) ltext(x,y,letterArg[subscripts[groups]])
)


Il est possible d'encapsuler cette fonction pour qu'elle fonctionne avec un data.frame de n'importe quel nom:

Code : Tout sélectionner

xyplot2 <- function (x, data, ...) {
    xyplot(x = x, data=data,
        letterA = data$letter,
        panel = function(x,y,subscripts,groups,letterA, ...) { ltext(x,y,letterA[subscripts[groups]]) }
    )
}
xyplot2(y~x|g, data=df)


Et si on pousse, on peut créer une fonction qui gère directement les paramètres, en ajoutant les colonnes supplémentaires, par exemple:

Code : Tout sélectionner

xyplot2 <- function(x, data, f, ...) {
    tmp <- as.list(data[, setdiff(colnames(data), all.vars(x)), drop = FALSE])
    eval(parse(text = paste(
        'xyplot(x = x, data = data,',
        paste(sapply(seq_along(tmp), function (i) { paste0(names(tmp)[i], "=tmp$", names(tmp)[i]) }), collapse = ","),
        ', panel = function(', paste("x", "y", "subscripts", "groups", paste(names(tmp), collapse = ","), sep = ","), ') { ', f, ' }',
        ')'
    )))
}

df <- expand.grid(x=1:3,y=1:4,g=factor(1:4))
df$letter <- sample(LETTERS,nrow(df),replace=TRUE)
df$colo <- sample(seq_along(LETTERS),nrow(df),replace=TRUE)

xyplot2(y~x|g, data=df, f = "ltext(x,y,letter[subscripts[groups]], col = colo)")

PS: le code est un peu moche, mais fonctionnel...
Mickaël
mickael.canouil.fr | rlille.fr

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Re: Lattice : passage des données à la fonction panel()

Messagepar François Bonnot » 10 Avr 2017, 06:21

Merci Mickaël,
C'est effectivement une façon de contourner le problème.
Mais je me demande pourquoi les concepteurs n'ont pas prévu au moins une option pour passer à la fonction panel() toutes les variables contenues dans le premier argument de xyplot(), car il est fréquent de devoir les utiliser dans la fonction panel().
François

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

Re: Lattice : passage des données à la fonction panel()

Messagepar Mickael Canouil » 10 Avr 2017, 09:22

Il est tout à fait possible de proposer/demander cette modification et ainsi la voir apparaitre dans une des prochaines itérations de R. Ou à défaut, obtenir la raison derrière le choix de ne pas passer toutes les colonnes de "data" en arguments.

Une raison évidente serait que le data.frame contiennent des milliers de colonnes, le passage de l'ensemble en arguments poserait de nombreux problèmes computationnelles. En règle générale, il est préférable de contraindre l'utilisateur dans un cadre fonctionnel et contrôler, plutôt qu'envisager un cadre "flexible" mais qui imposerait de contrôler tous les cas d'utilisations.
Mickaël
mickael.canouil.fr | rlille.fr

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Re: Lattice : passage des données à la fonction panel()

Messagepar François Bonnot » 11 Avr 2017, 06:30

Je pense qu'il doit être possible dans l'écriture de la fonction xyplot() de faire en sorte de passer seulement des variables spécifiées.
Mais je suis d'accord que le mieux est de s'adresser directement aux concepteurs.
Encore merci.
François


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité