Re: étiquettes superposées

From: Stephane DRAY (dray@biomserv.univ-lyon1.fr)
Date: Mon Nov 22 2004 - 17:12:27 MET

  • Next message: Jean Thioulouse: "Re: étiquettes superposées"

    Bonjour,
    concernant le zoom,
    je viens de bricoler une petite fonction "zoom" qui permet de selectionner
    une zone rectangulaire d'un graphique, et de zoomer dessus:

    zoom <- function(call.graph){
         appel<-as.list(match.call())
         appel.plot <- as.call(appel$call.graph)
         eval(appel.plot, sys.frame(0))
         appel.list <- as.list(appel.plot)
         dev0 <- dev.cur()
         windows()
         dev1 <- dev.cur()
         finished <- "c"
         while(finished!="q"){
             dev.set(dev0)
             xy <- locator(2)
             rect(xy$x[1],xy$y[1],xy$x[2],xy$y[2],border="red",lty=2)
             dev.set(dev1)
             appel.list$xlim <-range(xy$x)
             appel.list$ylim <-range(xy$y)
             cat("zoom in ", range(xy$x),"(x) and ", range(xy$y),"(y)\n")
             eval(as.call(appel.list), sys.frame(0))
             finished <- readline("Options: quit[q] refresh[r] continue[c] ")
             if(finished=="r"){
                 dev.set(dev0)
                 eval(appel.plot, sys.frame(0))
                 }
         }
    }

    > library(ade4)
    > x=rnorm(100)
    > y=rnorm(100)
    > zoom(s.label(cbind(x,y)))

    la fonction s'utilise sur un appel classique a un graphique. Elle ouvre
    deux fenetres:
    La premiere est celle du graphique demande, clique deux fois pour
    selectionner une zone rectangulaire (deux angles opposes). La zone
    selectionne est entoure d'unrectangle rouge.
    Puis, dans la deuxieme fenetre le meme grapghique est fait mais zoome sur
    la zone d'interet.
    alors allez dans la fenetre de commande, 3 options:
    q: quitter
    r: efface les carres rouges de la fenetre originales et attends une
    nouvelle selection
    c: pour selectionner une autre region sans effacer les precedentes.

    Ca ne marche que sur windows pour le moment car je fait un appel a
    windows() qui ouvre une nouvelle fenetre graphique sur windows. Je ne sais
    pas si il existe une fonction generale multi plateforme. sinon, il faudrait
    se servir de options()$device

    Si la fonction vous plait, on pourrait l'integrer dans une future version
    d'ade, apres amelioration ! J'attends vos commentaires.

    Cordialement.

    At 05:22 22/11/2004, alain guerreau wrote:

    >Le forum d'ADE4 s'anime autour de la question des « étiquettes » ; je m'en
    >réjouis, car c'est une difficulté qui m'irrite depuis le jour où j'ai
    >effectué mes premières analyses factorielles, en 1978 :-(( JP Benzécri
    >avait évacué la question en faisant réaliser les graphiques à la plume par
    >une « petite main ». A l'époque du FORTRAN (et de tout ce qui allait avec),
    >les listings comportaient, sous les graphiques, des listes (souvent longues)
    >de points superposés non imprimés, que l'on reportait donc au crayon, au
    >prix d'un effort très désagréable (variante de la méthode Benzécri ). Tout
    >le système graphique s'étant trouvé, depuis, bouleversé, on a pris
    >l'habitude, soit de tout afficher (d'où des gribouillis illisibles), soit de
    >n'afficher qu'une partie (une variante étant le principe des étiquettes
    >blanches d'ADE4). C'est, tout compte fait, presque pire que la méthode
    >Benzécri.
    >
    >Alors, pourquoi si peu de réflexions et d'efforts pour mettre au point une
    >solution réaliste ? Depuis les travaux de Jacques Bertin (début dans les
    >années 40, fin vers 1975), je n'ai vu apparaître, du moins en français,
    >aucune réflexion vraiment méthodique sur la « statégie graphique » dans le
    >domaine statistique. C'est pourtant un champ vaste et très prometteur. Mais
    >qui suppose que l'on accepte l'idée qu'une exploration statistique n'est pas
    >à 100% une affaire de maths et de théorèmes... Ici, pour faire très bref, je
    >rappellerais seulement :
    >1. qu'il est aisé de produire une infinité de graphiques inutiles et/ou mal
    >conçus ;
    >2. que l'on doit toujours partir de l'idée, défendue régulièrement sur le
    >forum ADE4, mais nulle part dans les manuels, que, dans la grande majorité
    >des cas, il existe une « pluralité de solutions optimales », ce qui implique
    >qu'un grand nombre de discussions sont en réalité sans objet ;
    >3. que l'on peut et doit généraliser cette proposition, tout simplement
    >parce qu'un paquet de données plus ou moins structurées, même de petite
    >taille, nécessite presque toujours un nombre important de graphiques (souven
    >t plusieurs variantes du même, mais avec des paramètres différents).
    >D'où l'idée, qui paraît trop simple pour être intéressante, que toute
    >écriture de fonction graphique doit comporter par principe la possibilité de
    >modifier un grand nombre de paramètres, de manière à permettre facilement la
    >production très rapide d'une série de graphiques entre lesquels on
    >déterminera empiriquement ceux sur lesquels on voit quelque chose et ceux
    >sur lesquels on ne voit rien. Discuter à perte de vue sur « le bon paramètre
    >de bandwidth », quel gaspillage !
    >
    >
    >Les étiquettes. Il faut faire en sorte de fournir au chercheur devant son
    >écran toutes les informations qui peuvent lui être utiles, et dont il peut
    >avoir besoin. Et ce, sans qu'il lui soit nécessaire de manipuler des tas de
    >fichiers dont il ignore d'ailleurs les noms... Mais il faut aussi tenir
    >compte de deux contraintes, une matérielle et une théorique. 1. l'écran ou
    >la feuille de papier n'ont qu'une taille limitée, 2. un bon graphique,
    >lisible et interprétable, implique que le lecteur ne soit pas submergé. Je
    >me limite ici aux analyses factorielles classiques.
    >En simplifiant à outrance, il me semble que l'on se trouve devant un
    >éventail de difficultés, en fonction du nombre d'étiquettes affichables.
    >Grosso modo (à la louche) : jusqu'à 50, je veux voir toutes les étiquettes
    >instantanément, sinon je juge la fonction mal foutue ; entre 50 et 250, ça
    >se discute : on peut estimer qu'un affichage général de toutes les
    >étiquettes va embrouiller au lieu de clarifier, mais l'inverse aussi, tout
    >dépend de la signification desdites étiquettes ; il est plus que souhaitable
    >qu'une possibilité d'affichage complet existe ; au-delà de 250, un affichage
    >complet des étiquettes ne paraît plus guère se justifier, il faut faire
    >ressortir des nuages de points significatifs ; on doit toutefois préserver
    >la possibilité de faire apparaître ponctuellement l'étiquette de tel ou tel
    >point (cas en général trop développé des outliers, mais qui existent tout de
    >même).
    >Techniquement (je parle en toute incompétence) : le dernier cas est sans
    >doute le plus simple, sous R existe la fonction identify(), facile à mettre
    >en oeuvre. On peut imposer quelques règles simples : pas d'étiquette de plus
    >de 6 caractères, un affichage modeste (cex=.5, par exemple). Surtout, il est
    >excessivement gênant que R ne dispose pas d'une fonction de « zoom » facile
    >à mettre en oeuvre (si je me trompe et si elle existe, mille mercis de me le
    >signaler). Je comprends encore bien moins pourquoi le paramètre din
    >(par(din)) est en read.only, et pourquoi on ne peut pas définir sous R une
    >image de taille quelconque dans laquelle on pourrait naviguer avec les
    >barres de déroulement. (il existe apparemment une possibilité sous Linux,
    >que je n'ai pas testée). Ce serait sans doute la meilleure solution pour la
    >zone médiane (50-250). Il faudra bien un jour ou l'autre aller maniper dans
    >les fonctions graphiques de base pour régler ce problème. Reste, en tout
    >état de cause, la question des points strictement superposés, qui le
    >resteront quelle que soit la taille de l'écran ou de la feuille. Je ne vois
    >pas qu'on puisse faire l'économie d'un algorithme spécifiquement dédié à
    >cette affaire. JP Benzécri aurait pu se fatiguer un peu plus. D'autant que,
    >comme le montre l'expérience (eh oui, « le privilège de l'âge », comme je
    >l'ai déjà lu dans ce forum...), les analyses factorielles les plus
    >intéressantes sont le plus souvent celles qui font apparaître des « paquets
    >de points », ou des zones de forte densité (type effet Gutmann). Et donc des
    >étiquettes majoritairement superposées. Le gribouillis gâche tout le plaisir
    >et empêche de comprendre ce qui se passe.
    >
    >
    >C'est dans ces tristes conditions que j'ai imaginé la possibilité d'une
    >fonction bancale et rudimentaire qui ferait disparaître cet inconvénient.
    >L'idée est d'une navrante simplicité :
    >1. calculer la distance de tous les points par rapport au centre du
    >graphique.
    >2. trier.
    >3. en partant du centre, et en prenant les points dans l'ordre de cette
    >liste, rechercher, pour chaque point et par rapport à lui, les points situés
    >en deçà d'une distance x en largeur et y en hauteur.
    >4. repousser vers l'extérieur (en fonction du cadrant dans lequel on se
    >trouve), tous les points ainsi repérés, de telle sorte qu'ils se retrouvent
    >au pire à ces distances critiques x et y.
    >5. continuer jusqu'à extinction de la liste.
    >
    >en pratique, des choix s'imposent ; en particulier, doit-on ou non
    >recalculer les distances au centre à chaque itération ? Sinon, repartir du
    >centre autant de fois que nécessaire ? (ou un compromis ??). La fonction
    >ci-dessous donne des résultats acceptables (c'est un avis) en dessous de 300
    >points. Au-delà, elle peut encore marcher, en théorie, mais les temps de
    >calcul s'allongent considérablement et finissent par tout bloquer. Surtout,
    >inconvénient majeur (que certains jugeront probablement dirimant), cet
    >algorithme déforme plus ou moins le nuage (dans des proportions très
    >variables, en fonction de la quantité de points et de leur répartition).
    >Pour mon usage personnel, je procède systématiquement en deux temps :
    >1.affichage complet brut (donne la forme exacte du nuage et divers
    >gribouillis), 2. affichage après passage de la fonction pousspouss(), nuage
    >plus ou moins déformé, mais toutes les étiquettes lisibles. Avec les deux
    >écrans ou les deux feuilles, je peux savoir immédiatement qui est qui, et
    >où. Avec moins de 50 points et des paramètres graphiques modestes, la
    >déformation est généralement à peine perceptible. Et quel confort !
    >
    >
    >Bien entendu, les remarques, critiques, et je l'espère les propositions de
    >modification / amélioration, me rendraient service. Cette fonction
    >(typiquement du « programme spaghetti ») est publique (type de toutes les
    >fonctions R). Il est à peu près certain qu'un algorithme meilleur doit
    >exister.
    >
    >
    >Alain Guerreau CNRS
    >
    >*******************************************
    >
    >"pousspouss" <-
    >function (x,y,lab="",cex=0.8, vert=1){
    >
    >eps <- 0.00000009
    >tabdep <- as.data.frame(cbind(x,y,lab))
    >tabdep$x <- as.numeric(as.character(tabdep$x))
    >tabdep$y <- as.numeric(as.character(tabdep$y))
    >tabdep$lab <- as.character(tabdep$lab)
    >for (i in 1:length(tabdep$x)){
    >tabdep$ind[i] <- i
    >tabdep$disct2[i] <- (tabdep$x[i]^2)+(tabdep$y[i]^2)}
    >carlar <- max(nchar(tabdep$lab))
    >r <- max((abs(max(tabdep$x)-min(tabdep$x))),
    >((abs(max(tabdep$y)-min(tabdep$y)))*1.3))
    >
    >recx <- r/(55/carlar/cex)
    >recy <- r/(40/cex)
    >
    >ord <- order(tabdep$disct2)
    >tabdep <- tabdep[ord,]
    >tabpro <- tabdep
    >i <- 1
    >fin <- length(tabdep$x)
    >
    >while (i <= fin){
    >px <- tabdep$x[i]
    >py <- tabdep$y[i]
    >ip <- NULL
    >for (j in 1:length(tabdep$x)){
    >if (i==j) next
    >dx <- px - tabdep$x[j]
    >dy <- py - tabdep$y[j]
    >if (abs(dx) < (recx-eps) && abs(dy) < (recy-eps)){
    >if ((abs(dy)*vert) <= abs(dx)){
    >tabdep$y[j] <- (py + (recy*sign(tabdep$y[j])))}
    >else {tabdep$x[j] <- (px + (recx*sign(tabdep$x[j])))}
    >ip <- c(ip , j)
    >}
    >}
    >i <- i+1
    >if (length(ip)> 0 && min(ip)< i) {
    >i <- min(ip)}
    >}
    >
    >ord2 <- order(tabdep$ind)
    >tabdep <- tabdep[ord2,]
    >return(tabdep)
    >}
    >
    >*******************************

    Stéphane DRAY
    --------------------------------------------------------------------------------------------------

    Département des Sciences Biologiques
    Université de Montréal, C.P. 6128, succursale centre-ville
    Montréal, Québec H3C 3J7, Canada

    Tel : (514) 343-6111 poste 1233 Fax : (514) 343-2293
    E-mail : stephane.dray@umontreal.ca
    --------------------------------------------------------------------------------------------------

    Web http://www.steph280.freesurf.fr/
    --------------------------------------------------------------------------------------------------



    This archive was generated by hypermail 2b30 : Mon Nov 22 2004 - 17:14:36 MET