如何在R和ggplot2中的背景图像上拟合图

问题描述 投票:5回答:2

我正在尝试拟合在背景图像上显示的图。由于锐度的损失,我无法过度拉伸图像。因此,我必须在背景图像上拟合图,这比图更薄。我不知道怎么做。请参阅附图:

Example plot

以下是示例R代码:

library(ggplot2)
library(readxl)
library(jpeg)
library(grid)

# find the ".jpg" image files and parse them to get the depth ranges for each image
setwd('~/R/Image_Example')
image_file <- "C1_9195-9197.jpg"
# read in the image file
img <- readJPEG(image_file)
g <- rasterGrob(img, interpolate = FALSE)

# read in the CT data
df_ct <- read_excel("CT_Doris25_short.xlsx", col_names = FALSE)

g_ct <- ggplot(data=df_ct) +
  annotation_custom(g, xmin=min(df_ct$X1), xmax=max(df_ct$X1), ymin=-Inf, ymax=Inf) +
  geom_path(aes_string(x=df_ct$X1, y=df_ct$X0), color='cyan') +
  scale_y_reverse() +
  theme(plot.margin = unit(c(0,0,0,0), "lines"))

g_ct

如你看到的,

  1. 我试图在annotation_custom中调整xmin和xmax。是否有一种方法可以使“青色”颜色显示的图形完全适合背景图像的“宽度”?我不介意图表是否更薄并且未显示X轴。事实上,当我使用gridExtra包装组合其他一些图表时,我就是这么做的。
  2. 我想在所示图像的顶部显示起始深度9195,并在图像底部显示结束深度9197。然后我不需要Y轴。我知道如何抑制X轴和Y轴标签的显示。所以这不是问题。我打开它们进行澄清。可以通过编程方式完成吗?
  3. 如您所见,沿Y轴的刻度以0.5为步长变化,即9195,9195.5,9196 ......等等。我想让它们以0.1而不是0.5的步长上升(或下降)。另外,我不想显示Y轴标签,只是勾选。图像顶部(9195)和底部(9197)的深度就足够了。

所以它应该看起来类似于下面显示的图像:

It should look like this...

请忽略左边的彩色情节,这是一个我无法摆脱的单独情节,否则我无法显示'滴答声'。它是使用MatLab完成的。我试图用R图替换MatLab图。 Matlab使用的TIFF图像更重,但也更清晰。我将使用JPEG,这是可以接受的。

谢谢你的时间。

r plot ggplot2 background-image
2个回答
5
投票

您可以在rasterGrob中设置宽度和高度参数,均等于1“npc”,这将强制图像填充绘图区域。然后在保存图像时指定图像的高度和宽度以获得所需的纵横比。 Theme和scale_y_reverse选项可用于控制轴的外观,如下所示。请注意,我们还可以使用expand参数来确保轴不会比图像或数据进一步延伸。

g <- rasterGrob(img, width=unit(1,"npc"), height=unit(1,"npc"), interpolate = FALSE)

g_ct <- ggplot(data=df_ct) +
  annotation_custom(g, -Inf, Inf, -Inf, Inf) +
  geom_path(aes_string(x=df_ct$X1, y=df_ct$X0), color='red', size=1) +
  scale_y_reverse("", 
                  labels = c(min(df_ct$X0), rep("", length(seq(min(df_ct$X0), max(df_ct$X0), 5))-2),max(df_ct$X0)), 
                  breaks = seq(min(df_ct$X0), max(df_ct$X0), 5),
                  expand = c(0,0)) +
  theme(plot.margin = unit(c(5,5,5,5), "mm"),
        axis.line.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.text.x = element_blank(),
        axis.line.y = element_blank(),
        axis.ticks.y = element_line(size = 1),
        axis.ticks.length = unit(5,'mm')) +
  scale_x_continuous("")
g_ct

ggsave('test.png', height=5, width = 2, units = 'in')

一些数据:

df_ct <- data.frame(X0 = 0:100)
df_ct$X1 = sin(df_ct$X0) +rnorm(101)

和背景图片:

https://i.stack.imgur.com/aEG7I.jpg

0
投票

除了@dww的答案。 如果你需要在数据点上覆盖(或者更确切地说是“底层”),而不是annotation_custom(g, -Inf, Inf, -Inf, Inf) 使用 annotation_custom(g, minX, maxX, minY, maxY) minX..maxY是图像角落在数据上的左下角到右上角。

然后,您还可以使用xlim(), ylim()自由缩放数据,而不会丢失图像数据位置关系。

示例(每个this SO问题下载图像)

download.file("https://upload.wikimedia.org/wikipedia/commons/b/b9/Sinusoidal_projection_SW.jpg",
              destfile="tmp.jpg", mode="wb")
world_image <- jpeg::readJPEG("tmp.jpg")
ggplot(FileWellsUsed, aes(y=Decimal.Latitude))   +
     annotation_custom(rasterGrob(world_image, 
                                  width = unit(1,"npc"), 
                                  height = unit(1,"npc")), 
                       -180, 180, -90, 90)+
       ggtitle("Sinusoidal projection") + 
       xlim(c(-180,180)) +ylim(c(-60,75))+
       coord_fixed() +
       ...yourdata.....

另请参阅this问题,该问题使用rasterGrid而不是rasterGrob。

© www.soinside.com 2019 - 2024. All rights reserved.