Changer la taille par défaut des graphiques

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

Gilles San Martin
Messages : 211
Enregistré le : 08 Juin 2007, 17:25

Changer la taille par défaut des graphiques

Messagepar Gilles San Martin » 13 Sep 2012, 19:53

Bonjour

J'aimerais savoir si il est possible de changer la taille par défaut des fenêtres graphiques apparaissant quand on utilise par exemple plot().

J'ai vu qu'il y a un paramètre par("din") qui donne les dimensions mais ne permet pas de les changer.

J'utilise d'habitude dev.new() pour spécifier la taille finale de ma fenêtre graphique à l'écran et adapter tous les autres paramètres en conséquence. J'utilise ensuite dev.print pour les sauver dans le format voulu.

Mon problème est que je veux utiliser la fonction spin() du package knitr pour réaliser des rapports facilement depuis un simple script R (en mélangeant graphiques et résultats d'analyse). Or quand j'utilise dev.new ou x11() il ne les imprime pas alors que si je fais mes graphiques dans la fenêtre graphique par défaut, ils apparaissent dans le rapport mais ils sont beaucoup trop grands.

Utiliser les devices pdf(), png(), ps() etc... n'est donc pas une solution.
Utiliser Sweave ou OdfWeave n'est pas une solution non plus car je veux rester dans un script R directement utilisable en tant que tel...

Merci d'avance

dicko ahmadou
Messages : 444
Enregistré le : 21 Nov 2009, 20:15

Messagepar dicko ahmadou » 13 Sep 2012, 22:08

knitr supporte une syntaxe de type Roxygen pour nommer les chunk et y mettre des options. Donc tu as une solution.
Voici un exemple simple qui te permettra de comprendre

Contenu du fichier graphknit.R

Code : Tout sélectionner

#' exemples avec des figures de tailles différentes
#' syntaxe de roxygen
require(knitr)

#' les données d'abord
set.seed(123)
x <- rnorm(10)
y <- rnorm(10)

#' graphique non ajusté
#+ graph-nonajust
plot(x, y)

#' Graphique ajusté
#+ graph-ajust, fig.width = 5, fig.height = 4
plot(x, y)


Ensuite si tu veux voir rapidement (en html par exemple)

Code : Tout sélectionner

essai <- spin("graphknit.R", knit = FALSE)
knit2html(essai)


Tu as des détails dans la documentation du package avec des exemples.
The best thing about being a statistician is that you get to play in everyone's backyard.
John Tukey

Stéphane Adamowicz
Messages : 206
Enregistré le : 07 Mar 2012, 10:13
Contact :

Messagepar Stéphane Adamowicz » 14 Sep 2012, 07:13

pourquoi ne pas utiliser simplement la fonction quartz() sur Mac ou windows() sur PC ? par exemple quartz(width=4, height=4), les dimensions étant en pouces ...

Sur Mac, il y a aussi une possibilité de réglage par défaut des fenêtres graphiques dans le menu Préférences
Stéphane Adamowicz
INRA, UR 1115 Plantes et Systèmes de Culture Horticoles (PSH)
domaine St Paul, site agroparc
84914 Avignon, cedex 9

Gilles San Martin
Messages : 211
Enregistré le : 08 Juin 2007, 17:25

Messagepar Gilles San Martin » 15 Sep 2012, 12:49

Merci à tous deux pour vos réponses

Stéphane : Je suis sous GNU/Linux où x11() est l'équivalent de windows() ou quartz() je pense. Et j'utilise préférentielelment dev.new() qui est équivalent et indépendant de la plateforme. Le problème est que knitr ne donne aucun graphique quand on utilise ces commandes.

Par exemple dans le code suivant : le graphique 1 devrait apparaître deux fois : une fois normalement et une fois en plus petit or seul le premier apparaît :

Code : Tout sélectionner

#' #Analyse simple
#+ datagen, echo=FALSE, results = 'markup'

# On génère qq données
d <- data.frame(var1 = rnorm(100), var2 = rnorm(100), var3 = rnorm(100), var4 = rnorm(100))
d$y <- d$var1 + 2*d$var3 + rnorm(100)

mod <- lm(y ~ var1, data=d)

# plot des données et du modèle
plot(y~var1, data=d)
abline(mod)

# la même chose en définissant la taille de la fenêtre --> pas imprimé par knitr
dev.new(height = 4, width = 4)
plot(y~var1, data=d)
abline(mod)
dev.off()

# résultats du modèle linéaire
summary (mod)   

# Plots de diagnostique du modèle
par(mfrow = c(2,2))
plot(mod)

Si ce script s'appelle "loop.R" on execute les comandes suivante pour obtenir le rapport :

Code : Tout sélectionner

library(knitr)
spin(hair = "loop.R" , knit = TRUE)
knit2html("loop.Rmd")


Dicko : ta solution est probablement ce qu'on peut faire de mieux en restant simple mais çà ne me satisfait pas pleinement (je sais, je suis difficile ;-) ). D'abord parce que çà m'oblige à changer mon script R spécialement pour le rapport (sans dev.new, dev.print ou une autre commande permettant de spécifier la taille de la fenêtre etc...) or l'avantage de spin() est, je trouve, justement d'éviter cela. J'aurais préféré une solution par exemple avec par(din= c(4,5)) qui me permettrait d'avoir le même code à la fois pour l'affichage à l'écran et le rapport. Mais je crains que je n'y échapperai pas.
L'autre problème est qu'on est obligé de fixer la taille des graphiques pour un "code chunk". Or ce type d'outils de reporting est particulièrement utile pour répéter la même analyse sur plusieurs objets avec une boucle. Et on voudrait pouvoir spécifier des tailles différentes pour les différents graphiques au sein de la boucle.
Par exemple pour les données ci-dessus on voudrait faire 5 régressions de Y en fonction de chaque variable (exemple un peu stupide j'en conviens...) et de sortir pour chaque un graphique des données avec une taille donnée puis les résultats de l'analyse suivi des graphiques diagnostiques des modèles qui auraient une taille différente :

Code : Tout sélectionner

#+ datagen, echo=FALSE, results = 'markup', warning = FALSE, error = FALSE, message = FALSE
# On génère qq données
d <- data.frame(var1 = rnorm(100), var2 = rnorm(100), var3 = rnorm(100), var4 = rnorm(100))
d$y <- d$var1 + 2*d$var3 + rnorm(100)

## # Analyses dans une boucle
#+ loop1, echo=FALSE, results = 'markup', fig.width= 6, fig.height = 6

models <- as.list(vector(length = nrow(d)-1)) # liste vide pour stocker les modèles
mod <- lm(y ~ var1, data=d)

for(i in 1:3) {

models[[i]] <- update(mod, .~ d[,i])

# plot des données et du modèle
print(colnames(d)[i])

par(mfrow = c(1,1))
plot(d$y ~ d[,i], main = colnames(d)[i])
abline (models[[i]])

# resultats du modèle linéaire
print(summary(models[[i]]))

# plots de diagnostique
par(mfrow = c(2,2))
plot(models[[i]])

}


Si on passe ce script par spin() et knit2html on se rend compte qu'il y a en plus un bug d'exécution dans les boucles. L'ordre des graphiques et des sorties de modèles n'est pas le bon. Apparemment le bug est connu mais je n'ai pas vu de solution :
https://github.com/hadley/evaluate/issues/14

J'espérais m'en sortir en utilisant une solution similaire à ce qu'on aurait fait avec Sweave (d'après le document de Jean Lobry) et results = 'tex' qui devient results = 'asis' dans knitr (en sauvant d'abord les graphiques sur le disque). Le problème c'est que les graphiques s'affichent en taille énorme et je ne vois pas comment on peut changer la taille des graphiques dans le langage markdown (ce serait impossible ???). On ne peut toujours pas utiliser dev.new/dev.print que j'ai du commenter pour que le code s'exécute correctement.

Code : Tout sélectionner

#' # Analyses dans une boucle avec results = 'asis' et stockage des graphiques sur le disque
#+ loop3, echo=FALSE, results = 'markup', warning = FALSE, error = FALSE, message = FALSE

d <- data.frame(var1 = rnorm(100), var2 = rnorm(100), var3 = rnorm(100), var4 = rnorm(100))
d$y <- d$var1 + 2*d$var3 + rnorm(100)
mod <- lm(y ~ var1, data=d)

dir.create(file.path(getwd(), "mygraphs")) # répertoire pour stocker les graphiques
models <- as.list(vector(length = nrow(d)-1)) # liste vide pour stocker les modèles

for(i in 1:3) {

   models[[i]] <- update(mod, .~ d[,i])

   # graphique des données et du modèle
#   dev.new(width = 7/cm(1), height = 7/cm(1))
   png(paste("mygraphs/",colnames(d)[i],".png",sep=""),width= 7/cm(1), height= 7/cm(1), units="in", res = 300)
   par(mfrow = c(1,1))
   plot(d$y ~ d[,i], main = colnames(d)[i])
   abline (models[[i]])
#   dev.print(device = png, filename = paste("mygraphs/",colnames(d)[i],".png",sep=""),width= 7/cm(1), height= 7/cm(1), units="in", res = 300)
   dev.off()

   # graphiques diagnostiques
#   dev.new(width = 15/cm(1), height = 15/cm(1))
   png(filename = paste("mygraphs/diag",colnames(d)[i],".png",sep=""),width= 15/cm(1), height= 15/cm(1), units="in", res = 300)
   par(mfrow = c(2,2))
   plot(models[[i]])
#   dev.print(device = png, filename = paste("mygraphs/diag",colnames(d)[i],".png",sep=""),width= 15/cm(1), height= 15/cm(1), units="in", res = 300)
   dev.off()

}

# On imprime ce qu'on veut voir dans le rapport
#+ pri, echo=FALSE, results = 'asis', warning = FALSE, error = FALSE, message = FALSE

for(i in 1:3) {
   
   #Titre
   cat(paste("\n##", colnames(d)[i]), "\n")
   
   # graphique 1
   cat(paste("![aa](mygraphs/",colnames(d)[i],".png)",sep=""))

   # résultats de la régression
   cat("\n\n```\n\n")
   print(summary(models[[i]]))
   cat("\n\n```\n\n")

   # graphique 2
   cat(paste("![bb](mygraphs/diag",colnames(d)[i],".png)",sep=""))

   }


Finalement çà fonctionne plus ou moins en utilisant directement du HTML et en spécifiant WIDTH='n%' dans les balises images. Mais çà deviens fort compliqué et plus tellement différent de solutions comme R2HTML ou même d'utiliser cat(file =):




Code : Tout sélectionner

#' <h1>Analyses dans une boucle avec results = 'asis' et stockage des graphiques sur le disque</h1>
#+ loop3, echo=FALSE, results = 'markup', warning = FALSE, error = FALSE, message = FALSE

d <- data.frame(var1 = rnorm(100), var2 = rnorm(100), var3 = rnorm(100), var4 = rnorm(100))
d$y <- d$var1 + 2*d$var3 + rnorm(100)
mod <- lm(y ~ var1, data=d)

dir.create(file.path(getwd(), "mygraphs")) # répertoire pour stocker les graphiques
models <- as.list(vector(length = nrow(d)-1)) # liste vide pour stocker les modèles

for(i in 1:3) {

   models[[i]] <- update(mod, .~ d[,i])

   # graphique des données et du modèle
#   dev.new(width = 7/cm(1), height = 7/cm(1))
   png(paste("mygraphs/",colnames(d)[i],".png",sep=""),width= 7/cm(1), height= 7/cm(1), units="in", res = 300)
   par(mfrow = c(1,1))
   plot(d$y ~ d[,i], main = colnames(d)[i])
   abline (models[[i]])
#   dev.print(device = png, filename = paste("mygraphs/",colnames(d)[i],".png",sep=""),width= 7/cm(1), height= 7/cm(1), units="in", res = 300)
   dev.off()

   # graphiques diagnostiques
#   dev.new(width = 15/cm(1), height = 15/cm(1))
   png(filename = paste("mygraphs/diag",colnames(d)[i],".png",sep=""),width= 15/cm(1), height= 15/cm(1), units="in", res = 300)
   par(mfrow = c(2,2))
   plot(models[[i]])
#   dev.print(device = png, filename = paste("mygraphs/diag",colnames(d)[i],".png",sep=""),width= 15/cm(1), height= 15/cm(1), units="in", res = 300)
   dev.off()

}

#+ printhtml, echo=FALSE, results = 'asis', warning = FALSE, error = FALSE, message = FALSE

for(i in 1:3) {
   
   #Titre
   cat(paste("\n<h2>", colnames(d)[i]), "</h2>\n")
   
   # graphique 1
   cat(paste("\n<p><img src=\"",getwd(), "/mygraphs/",colnames(d)[i],".png\" WIDTH=\"35%\" /> </p>",sep=""))

   # résultats de la régression
   cat("\n<pre><code> \n")
   print(summary(models[[i]]))
   cat("\n</code></pre>\n")

   # graphique 2
   cat(paste("\n<p><img src=\"",getwd(), "/mygraphs/diag",colnames(d)[i],".png\" WIDTH=\"60%\" /> </p>",sep=""))

   }


Si ce script s'appelle "loop_for_html.R" on doit exécuter les commandes suivantes pour obtenir le rapport :

Code : Tout sélectionner

library(knitr)
spin(hair = "loop_for_html.R" , knit = TRUE, format = c("Rhtml"))
knit2html("loop_for_html.Rhtml",fragment.only=FALSE)


Si quelqu'un à une solution plus simple, je suis preneur.
Dans l'état actuel il me semble que knitr n'est utilisable que pour les rapports les plus simples (et sans graphiques dans des boucles en tous cas ). Ce qui est bien dommage...

Stéphane Adamowicz
Messages : 206
Enregistré le : 07 Mar 2012, 10:13
Contact :

dev.new

Messagepar Stéphane Adamowicz » 17 Sep 2012, 07:19

Merci de m'avoir mis le nez sur dev.new() dont j'ignorais l'existence et qui pourrait bien remplacer quartz() dans mes futurs scripts.

N'étant pas non plus utilisateur de knitr, je n'ai qu'une suggestion naïve à faire : as tu essayé en supprimant l'instruction dev.off() ?
Stéphane Adamowicz

INRA, UR 1115 Plantes et Systèmes de Culture Horticoles (PSH)

domaine St Paul, site agroparc

84914 Avignon, cedex 9

Gilles San Martin
Messages : 211
Enregistré le : 08 Juin 2007, 17:25

Messagepar Gilles San Martin » 18 Sep 2012, 13:21

Tant mieux pour dev.new(). J'ai moi-même découvert cette fonction sur ce forum il y a quelques temps.
Enlever le dev.off() ne change rien...

Par contre pour ce qui est de spécifier la taille des graphiques dans un fichier markdown, l'astuce est qu'on peut y intégrer du code HTML. Donc pour l'exemple ci-dessus si on veut par exemple des graphiques plus petits et centrés :

Code : Tout sélectionner

#+ pri, echo=FALSE, results = 'asis', warning = FALSE, error = FALSE, message = FALSE

for(i in 1:3) {
   
   #Titre
   cat(paste("\n##", colnames(d)[i]), "\n")
   
   # graphique 1   
   cat(paste("\n<p align=center><img src=\"",getwd(), "/mygraphs/",colnames(d)[i],".png\" WIDTH=\"35%\" /> </p>",sep=""))

   # résultats de la régression
   cat("\n\n```\n\n")
   print(summary(models[[i]]))
   cat("\n\n```\n\n")

   # graphique 2
   cat(paste("\n<p align=center><img src=\"",getwd(), "/mygraphs/diag",colnames(d)[i],".png\" WIDTH=\"60%\" /> </p>",sep=""))

   }


Retourner vers « Questions en cours »

Qui est en ligne

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