Как использовать изображение в качестве точки в ggplot?
Есть ли способ использовать определенное маленькое изображение в качестве точки на диаграмме рассеяния с помощью ggplot2. В идеале я хочу изменить размеры изображений на основе переменной.
Вот пример:
library(ggplot2)
p <- ggplot(mtcars, aes(wt, mpg))
p + geom_point(aes(size = qsec, shape = factor(cyl)))
Поэтому я хочу знать, есть ли способ предоставить конкретное изображение в виде фигуры?
3 ответа
Есть библиотека под названием ggimage
сделать это. Смотрите вступительную виньетку здесь
Вам просто нужно добавить столбец к вашему data.frame
с адресом изображений, которые могут быть сохранены в Интернете или локально на вашем компьютере, а затем вы можете использовать geom_image()
:
library("ggplot2")
library("ggimage")
# create a df
set.seed(2017-02-21)
d <- data.frame(x = rnorm(10),
y = rnorm(10),
image = sample(c("https://www.r-project.org/logo/Rlogo.png",
"https://jeroenooms.github.io/images/frink.png"),
size=10, replace = TRUE)
)
# plot2
ggplot(d, aes(x, y)) + geom_image(aes(image=image), size=.05)
пс. Обратите внимание, что ggimage
зависит от EBImage. Итак, чтобы установить gginamge
Я должен был сделать это:
# install EBImage
source("https://bioconductor.org/biocLite.R")
biocLite("EBImage")
# install ggimage
install.packages("ggimage")
Вот минималистский geom для отображения растровых изображений вместо точек,
library(ggplot2)
library(grid)
## replace by a named list with matrices to be displayed
## by rasterGrob
.flaglist <- list("ar" = matrix(c("blue", "white", "blue"), 1),
"fr" = matrix(c("blue", "white", "red"), 1))
flagGrob <- function(x, y, country, size=1, alpha=1){
grob(x=x, y=y, country=country, size=size, cl = "flag")
}
drawDetails.flag <- function(x, recording=FALSE){
for(ii in seq_along(x$country)){
grid.raster(x$x[ii], x$y[ii],
width = x$size[ii]*unit(1,"mm"), height = x$size[ii]*unit(0.5,"mm"),
image = .flaglist[[x$country[[ii]]]], interpolate=FALSE)
}
}
scale_country <- function(..., guide = "legend") {
sc <- discrete_scale("country", "identity", scales::identity_pal(), ..., guide = guide)
sc$super <- ScaleDiscreteIdentity
class(sc) <- class(ScaleDiscreteIdentity)
sc
}
GeomFlag <- ggproto("GeomFlag", Geom,
required_aes = c("x", "y", "country"),
default_aes = aes(size = 5, country="fr"),
draw_key = function (data, params, size)
{
flagGrob(0.5,0.5, country=data$country, size=data$size)
},
draw_group = function(data, panel_scales, coord) {
coords <- coord$transform(data, panel_scales)
flagGrob(coords$x, coords$y, coords$country, coords$size)
}
)
geom_flag <- function(mapping = NULL, data = NULL, stat = "identity",
position = "identity", na.rm = FALSE, show.legend = NA,
inherit.aes = TRUE, ...) {
layer(
geom = GeomFlag, mapping = mapping, data = data, stat = stat,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, ...)
)
}
set.seed(1234)
d <- data.frame(x=rnorm(10), y=rnorm(10),
country=sample(c("ar","fr"), 10, TRUE),
stringsAsFactors = FALSE)
ggplot(d, aes(x=x, y=y, country=country, size=x)) +
geom_flag() +
scale_country()
(вывод из пакета ggflags)
Во-первых, вот ваш ответ:
Чтобы показать вам, как использовать то, как вы могли бы лучше использовать виджеты для представления дифференциации данных, я отсылаю вас к примеру граней chernoff в галерее графа R.:
http://addictedtor.free.fr/graphiques/graphiques/graph_87.png
Весь код для генерации этого примера доступен на сайте.
В качестве альтернативы посмотрите ggplot stat_spoke для простого виджета: http://had.co.nz/ggplot2/graphics/706b1badf6469940342f204b7bc98857.png
grImport предоставляет механизм для импорта простых PDF-изображений на график для использования в качестве точек.
Теперь следует критика вашего примера.
Это не диаграмма рассеяния. По сути, это потоковый список упорядоченных точек данных, где цвет используется для обозначения одной из текстовых переменных, а неинформативный и избыточный виджет использовался для обрамления данных, но в остальном не обеспечивает визуальной обратной связи с точки зрения размера или формы.
Это не очень хороший график, потому что он полностью не отвечает на поставленный вопрос "Платит ли больше, приводит к лучшим результатам" и заставляет читателя усердно делать этот вывод (и этот другой график, если необходимо) самостоятельно.
Кроме того, авторы потратили впустую оси X, Y - которые могли бы быть хорошо использованы для позиционирования элементов по исходящим данным и результатам, чтобы обеспечить визуальное понимание соотношения цены и качества. Вместо этого они решили упорядочить значки по соотношению стоимости на душу населения к средней ставке выпускников, что является своего рода полезным, но не отвечает на поставленный вопрос и не позволяет провести прямое визуальное сравнение относительного соотношения между колледжами, или связь между стоимостью и стоимостью.
Как я уже сказал, на мой взгляд, это плохой график, и вашим читателям было бы плохо, если бы вы его повторили.