r - 使用自定义图像而不是 R 折线图标记的标准形状

标签 r

R 有许多标准符号/形状,可以用作 R 折线图中数据点的标记(如果有歧义,请参阅 http://www.cookbook-r.com/Graphs/Shapes_and_line_types/ 了解我的意思)。

我想要做的是使用我自己的自定义图标(例如苹果、香蕉、樱桃等的 GIF)来代替标准形状。

我怎样才能在 R 中做到这一点?不必是原生 R 图形,我可以使用诸如 ggplot2 等软件包。

我的预期用途是在折线图中,其中标记也将出现在图例上。

这里的答案( Labelling the plots with images on graph in ggplot2 )通过直接绘制图像来解决类似的问题,就好像它们是独立的项目一样,因此与数据/图例没有真正的联系。

最佳答案

我不知道如何使用与geom_point一起使用的自定义点标记(尽管您可以按照@baptiste的建议创建自己的geom)。但是,如果您愿意忍受一些编码痛苦,则可以使用 annotation_custom 创建类似于使用 geom_point 获得的内容。痛苦的部分是您必须进行一些手动调整(尽管您可能会创建编程逻辑来为您处理其中的一些内容,如果您要经常这样做的话)。情节渲染也非常缓慢。尽管如此,尝试一下还是很有趣的。

加载包并获取两个图像,它们将成为我们的点标记:

library(ggplot2)
library(RCurl)
library(jpeg)
library(grid)

## Image 1
URL1 = "http://www.entertainmentearth.com/images/AUTOIMAGES/QMSER0179lg.jpg"
serenity = readJPEG(getURLContent(URL1))

## Image 2
URL2 = "http://cdn.pastemagazine.com/www/articles/2010/03/12/malcolm_reynolds.jpg"
mal = readJPEG(getURLContent(URL2))

# Crop the mal image
mal = mal[40:250,,]

## Turn images into raster grobs
serenity = rasterGrob(serenity)
mal = rasterGrob(mal)

# Make the white background transparent in the serenity image
serenity$raster[serenity$raster=="#FFFFFF"] = "#FFFFFF00" 

创建虚假数据并设置情节:

# Create fake data
df = data.frame(x=rep(1:4,2), y=c(1,1,2,4,6.5,5,5.5,4.8), g=rep(c("s","m"),each=4))

# Set up a plot
p = ggplot(df, aes(x, y, group=g)) + 
  geom_line() +
  theme_bw()

现在,使用 annotation_custom 将图像绘制为点标记,而不是使用几何图形。 annotation_custom 似乎一次只能处理一个点,而不是点向量,因此我们将使用 for 循环来绘制每个点。我们想要绘制两个不同的图像,因此我们将为每个图像使用一个单独的循环:

a=0.8
for (i in rownames(df[df$g=="s",])) {
  p = p + annotation_custom(serenity, df[i,"x"]-a,df[i,"x"]+a,df[i,"y"]-a,df[i,"y"]+a)  
}

b=0.4
for (i in rownames(df[df$g=="m",])) {
  p = p + annotation_custom(mal, df[i,"x"]-b,df[i,"x"]+b,df[i,"y"]-b,df[i,"y"]+b)  
}

最后,添加图例并关闭剪切,以便图例显示在最终绘图上:

a = 0.8*a
b = 0.8*b

p = p + coord_cartesian(xlim=c(0,5), ylim=c(0,7)) +
  theme(plot.margin=unit(c(1,10,1,1),"lines")) +
  annotation_custom(serenity, 5.8-a,5.8+a,3.4-a,3.4+a) +
  annotate(geom="text", x=5.8+0.5, y=3.4, label="Serenity", hjust=0) +
  annotation_custom(mal, 5.8-b,5.8+b,4.6-b,4.6+b) +
  annotate(geom="text", x=5.8+0.5, y=4.6, label="Mal", hjust=0)

# Turn off clipping
p <- ggplot_gtable(ggplot_build(p))
p$layout$clip <- "off"
grid.draw(p)

enter image description here

更新:新的 ggimage package最终可能会让这变得更容易一些。下面是一个例子。我想对最终的情节进行一些改进。

  • 更改绘图的纵横比也会更改图像的纵横比,但我希望图像保持其原始纵横比。

  • Serenity 图像具有白色背景,覆盖了绘图网格和 Mal 图像(因为 Serenity 是在 Mal 之后绘制的)。在上面的示例中,我将白色背景设置为透明。然而,即使我将上面创建的栅格图像保存为 jpeg(以便我可以使用具有透明背景的 Serenity 版本)并重新加载它们(而不是像下面那样直接从 URL 获取图像),Serenity 的图像仍然有白色背景。

  • 图例不使用图像作为“点标记”,而是在标记通常所在的位置留有空白。

也许该软件包的 future 版本将创造与这些问题相关的额外灵 active ,或者可能已经有一种我不知道的方法来解决这些问题。

df = data.frame(x=rep(1:4,2), y=c(1,1,2,4,6.5,5,5.5,4.8), 
                Firefly=rep(c("Serenity","Mal"),each=4),
                image=rep(c("http://www.entertainmentearth.com/images/AUTOIMAGES/QMSER0179lg.jpg",
                            "http://cdn.pastemagazine.com/www/articles/2010/03/12/malcolm_reynolds.jpg"), each=4))

ggplot(df, aes(x, y)) + 
  geom_line(aes(group=Firefly)) +
  geom_image(aes(image=image, size=Firefly)) +
  theme_bw() +
  scale_size_manual(values=c(0.1,0.15)) +
  coord_fixed(ratio=2/3, xlim=c(0.5, 4.5), ylim=c(0,7))

enter image description here

关于r - 使用自定义图像而不是 R 折线图标记的标准形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34847598/

相关文章:

r - 合并多列/堆叠多列

r - 将二进制样本转换为数字

rPlot 工具提示问题

r - 在R中使用mfrow:如何为每个子图赋予不同的y标签和x轴一个标签

r - 在 R 中使用 Leaflet 时如何在 addCircleMarkers() 中指定半径单位

r - 如何在删除提示后始终如一地绘制一棵树?

r - 使用从 tidyr 收集改变了我的回归结果

r - 如何从使用内联 C++ 过渡到制作自己的 R 包?

r - 如何将数据框分成两列并根据组更有效地计算行数

r - 如何在 Shiny 上通过 downloadHandler 下载工作簿?