Comment réparer le rapport hauteur / largeur dans ggplot?

88

J'essaie de redimensionner un tracé pour l'adapter à mon document, mais j'ai des difficultés à faire en sorte que le diagramme tracé soit un carré.

Exemple:

pdf(file = "./out.pdf", width = 5, height = 5)
p <- ggplot(mydata, aes(x = col1, y = col2))
print(p)
aux <- dev.off()

Bien que les limites pour x et y soient les mêmes, le tracé du résultat n'est pas carré. Je suppose que R rend le panneau englobant 5x5 "mais ne se soucie pas de la taille réelle du diagramme.

Comment puis-je retirer mes diagrammes?

htorque
la source

Réponses:

113

Dans ggplotle mécanisme pour conserver le rapport hauteur / largeur de votre tracé consiste à ajouter une coord_fixed()couche au tracé. Cela conservera le rapport hauteur / largeur du tracé lui-même, quelle que soit la forme du cadre de délimitation réel.

(Je vous suggère également d'utiliser ggsavepour enregistrer votre tracé résultant dans pdf / png / etc, plutôt que dans la pdf(); print(p); dev.off()séquence.)

library(ggplot2)
df <- data.frame(
    x = runif(100, 0, 5),
    y = runif(100, 0, 5))

ggplot(df, aes(x=x, y=y)) + geom_point() + coord_fixed()

entrez la description de l'image ici

Andrie
la source
3
Savez-vous pourquoi ggplot insiste pour placer l'étiquette de l'axe y vers la gauche? J'aimerais savoir comment éviter cela ...
Chase
@chase Une solution de contournement kludgy consiste à modifier la hjustposition du titre - essayez opts(axis.title.y=theme_text(hjust=10)). Mais, malheureusement, cela ne semble pas. Consultez groups.google.com/group/ggplot2/browse_thread/thread/… pour une discussion sur la liste de diffusion ggplot et la réponse de @ Baptiste.
Andrie
3
Ce comportement est corrigé dans la version de développement.
hadley
5
Avec le titre plus général de la question, pourriez-vous peut-être aussi ajouter des informations sur la façon de calculer le rapport (l'argument pour coord_fixed) étant donné que l'on n'utilise pas les mêmes limites sur les deux axes?
htorque
1
Suite au commentaire de @ htorque; si y est plutôt défini comme y=runif(100, 0, 50)alors l'aspect du tracé n'est plus carré. coord_fixed()fait que l'échelle de chaque axe est égale seulement il semble?
un autre ben
79

Pour garantir un rapport hauteur / largeur particulier, par exemple pour le carré, utilisez theme(aspect.ratio=1).

La réponse d'Andrie ne donne pas une image complète, car l'exemple fournit peut-être des données non naturelles où la plage de x est égale à la plage de y. Si toutefois les données étaient:

df <- data.frame(
  x = runif(100, 0, 50),
  y = runif(100, 0, 5))
ggplot(df, aes(x=x, y=y)) + geom_point() + coord_fixed()

alors l'intrigue ressemblerait à ceci:

entrez la description de l'image ici

La fonction coord_fixed () a également un argument pour ajuster le rapport des axes:

ratio rapport hauteur / largeur, exprimé en y / x

Pour que l'intrigue puisse être carrée avec:

ggplot(df, aes(x=x, y=y)) + geom_point() + coord_fixed(ratio=10)

entrez la description de l'image ici

Mais vous devez ajuster cela avec les limites des variables ou de la zone de tracé (toutes les limites ne sont pas bien divisibles par des nombres entiers comme ces exemples).

un autre ben
la source
12

Par souci d'exhaustivité: si vous souhaitez prendre en compte des limites d'axe très différentes:

df <- data.frame(
  x = runif(100, 0, 5000),
  y = runif(100, 0, 5))
ratio.display <- 4/3
ratio.values <- (max(df$x)-min(df$x))/(max(df$y)-min(df$y))
plot <- ggplot(df, aes(x=x, y=y)) + geom_point()
plot + coord_fixed(ratio.values / ratio.display)

Résultant en:

Graipher
la source
14
comment est-ce mieux que plot + theme(aspect.ratio=4/3)? Le ggplot peut avoir plusieurs couches, avec plusieurs ensembles de données, et les axes peuvent avoir des facteurs d'expansion arbitraires, de sorte que le calcul du rapport y / x à partir d'une source de données semble assez fragile.
baptiste du
2
Parce que ce n'est apparemment pas facilement découvrable. Ce qui est prouvé par le fait qu'il y a trois réponses ici, mais aucune ne le mentionne. Vous devriez le mettre dans une réponse, c'est certainement la meilleure solution.
Graipher