3 votes

Est-il possible de tracer des images dans un tracé ggplot2, qui ne soient pas déformées lorsque vous les enregistrez dans un rapport d'aspect non standard ?

Je suis à la recherche de toute solution à ce problème, quels que soient les paquets utilisés.

Le problème qui se pose est que les images tracées sont déformées lorsque vous les sauvegardez à l'aide de la fonction ggsave . Laissez-moi vous donner un exemple :

image_links = data.frame(id = c(1,2,3,4,5),
                         image = c("https://cdn.shopify.com/s/files/1/1061/1924/products/Smiling_Emoji_with_Eyes_Opened_large.png",
                                   "https://cdn.shopify.com/s/files/1/1061/1924/products/Smiling_Emoji_with_Smiling_Eyes_large.png",
                                   "https://cdn.shopify.com/s/files/1/1061/1924/products/Hushed_Face_Emoji_large.png",
                                   "https://cdn.shopify.com/s/files/1/1061/1924/products/Disappointed_but_Relieved_Face_Emoji_large.png",
                                   "https://cdn.shopify.com/s/files/1/1061/1924/products/Expressionless_Face_Emoji_large.png"))

mydata = data.frame(x = rnorm(100, mean = 50, sd = 20),
                    y = rnorm(100, mean = 50, sd = 5),
                    id = rep(c(1,2,3,4,5), 20))

mydata$y = mydata$y - 10*mydata$id

mydata = mydata %>% left_join(image_links, by='id')

g <- ggplot(mydata) + geom_image(aes(x=x, y=y, image=image), size=0.05)

ggsave(g, filename='[INSERT PATH HERE].png', width=width, height=height, dpi=300)

Cela fonctionne bien : The emoji's are displayed fine.

Le problème se pose lorsque vous ajustez le width y height les paramètres de ggsave par exemple parce que vous voulez que les axes x et y soient dans la bonne proportion :

width = (max(mydata$x) - min(mydata$x))/10
height = (max(mydata$y) - min(mydata$y))/10

ggsave(g, filename='[INSERT PATH HERE].png', width = width, height=height, dpi=300)

Les axes x et y sont maintenant corrects, mais les images sont déformées : Emojis are distorted

Cela se produit dans N'IMPORTE QUELLE situation où vous tracez une image mais où la width / height est différent du rapport d'aspect original de l'image que vous voulez ajouter.

Je recherche toute solution à ce problème, sans nécessairement se limiter à ggimage . Il me semble très étrange que vous ne puissiez pas ajouter correctement des images à un ggplot, car j'imagine qu'il est très courant pour les gens de vouloir le faire.

5voto

teunbrand Points 17490

Je ne connais pas bien ggsave, mais cela semble être un problème lié aux unités relatives par rapport aux unités absolues. Probablement que le geom_image() calcule les positions par rapport aux axes, qui sont déformées lorsque les axes sont redimensionnés (par exemple, dans le cadre de l'application de l'option ggsave ). Par exemple :

ggplot(mydata) + geom_image(aes(x=x, y=y, image=image), size=0.05)

Peut ressembler :

enter image description here

Ou peut ressembler :

enter image description here

Selon la fenêtre de l'appareil que je peux redimensionner à volonté.

Il y a deux façons de résoudre ce problème, qui impliquent toutes deux de recalculer les tailles des rasters au moment du dessin. La solution la plus simple est celle décrite ci-dessous.

# Get plot
g <- ggplot(mydata) + geom_image(aes(x=x, y=y, image=image), size=0.05)

# Convert to gtable
gt <- ggplotGrob(g)

# Get the imagegrobs, correct slots found by trial and error
imagegrobs <- gt$grobs[[6]]$children[[3]]$children

# Re-class them to a custom, made-up class
imagegrobs <- lapply(imagegrobs, function(image) {
  class(image) <- c("fixasp_raster", class(image))
  image
})

# Put them back into the gtable
gt$grobs[[6]]$children[[3]]$children <- imagegrobs 

Maintenant que nous avons une classe personnalisée pour ces images, nous pouvons écrire un morceau de code qui sera exécuté au moment du dessin en écrivant une méthode pour notre classe à l'aide du générique S3. makeContent du paquet de la grille.

library(grid)
makeContent.fixasp_raster <- function(x) {
  # Convert from relative units to absolute units
  h <- convertHeight(x$height, "cm", valueOnly = TRUE)
  w <- convertWidth(x$width, "cm", valueOnly = TRUE)
  # Decide how the units should be equal
  x$height <- x$width <- unit(sqrt(h * w), "cm")
  x
}

Notez que prendre la racine carrée du produit est improvisé, je ne sais pas si c'est la procédure optimale.

Lorsque nous traçons les données maintenant, nous aurons une taille cohérente des images, quel que soit le rapport d'aspect :

grid.newpage(); grid.draw(gt)

enter image description here enter image description here

La deuxième façon de résoudre ce problème est de déposer un problème sur la page github de l'initiative de l'UE sur la santé. ggimage en motivant votre cas d'utilisation et en les convainquant de mettre en œuvre quelque chose qui répond à vos préoccupations. S'ils le souhaitent, ils peuvent apporter un correctif au niveau de ggproto, afin que vous n'ayez pas à vous frotter à gtables.

1voto

Nils Mackay Points 128

La réponse de @teunbrand a été implémentée dans la version 0.2.4 de l'application de développement. ggimage . Vous pouvez installer la dernière version de dev comme ceci :

setRepositories(ind=1:2)
## install.packages("devtools")
devtools::install_github("GuangchuangYu/ggimage")

Cela devrait résoudre les problèmes de ratio d'aspect.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X