【问题标题】:Custom legend with imported images带有导入图像的自定义图例
【发布时间】:2016-03-21 14:14:05
【问题描述】:

我目前正在通过导入自定义图像并将它们用作 geom_points 在 ggplot2 中创建绘图,类似于 this post,但我正在循环浏览不同的图像以获得一个因素的独特水平。

有没有一种简单的方法可以将这些图像添加到图例中?我在 ggplot2 中看到了多篇关于自定义图例的帖子,但没有任何内容涉及导入的图像。

【问题讨论】:

  • “有没有一种简单的方法可以将这些图像添加到图例中?” 我不这么认为,我想你必须通过它来破解它在绘图区域之外禁用剪辑/启用绘图,然后构建您自己的图例。但我也很想知道。
  • 这个答案可能有用:stackoverflow.com/a/36172385/471093(也在原理证明中ggflags package

标签: r ggplot2 legend


【解决方案1】:

我不确定您将如何生成绘图,但这显示了一种用图像替换图例键的方法。它使用 grid 函数来定位包含图例键 grobs 的视口,并将其中一个替换为 R 标志

library(png)
library(ggplot2)
library(grid)

# Get image
img <- readPNG(system.file("img", "Rlogo.png", package="png"))

# Plot
p = ggplot(mtcars, aes(mpg, disp, colour = factor(vs))) + 
    geom_point() +
    theme(legend.key.size = unit(1, "cm"))

# Get ggplot grob
gt = ggplotGrob(p)
grid.newpage()
grid.draw(gt)

# Find the viewport containing legend keys
current.vpTree() # not well formatted
formatVPTree(current.vpTree())  # Better formatting - see below for the formatVPTree() function

    # Find the legend key viewports
    # The two viewports are: 
      # key-4-1-1.5-2-5-2
      # key-3-1-1.4-2-4-2

# Or search using regular expressions
Tree = as.character(current.vpTree())
pos = gregexpr("\\[key.*?\\]", Tree)
match = unlist(regmatches(Tree, pos))

match = gsub("^\\[(key.*?)\\]$", "\\1", match) # remove square brackets
match = match[!grepl("bg", match)]  # removes matches containing bg

# Change one of the legend keys to the image
downViewport(match[2])
grid.rect(gp=gpar(col = NA, fill = "white"))
grid.raster(img, interpolate=FALSE)
upViewport(0)

# Paul Murrell's function to display the vp tree 
formatVPTree <- function(x, indent=0) {
    end <- regexpr("[)]+,?", x)
    sibling <- regexpr(", ", x)
    child <- regexpr("[(]", x)
    if ((end < child || child < 0) && (end < sibling || sibling < 0)) {
        lastchar <- end + attr(end, "match.length")
        cat(paste0(paste(rep("  ", indent), collapse=""), 
                   substr(x, 1, end - 1), "\n"))
        if (lastchar < nchar(x)) {
            formatVPTree(substring(x, lastchar + 1), 
                         indent - attr(end, "match.length") + 1)
        }
    }
    if (child > 0 && (sibling < 0 || child < sibling)) {
        cat(paste0(paste(rep("  ", indent), collapse=""), 
                   substr(x, 1, child - 3), "\n"))
        formatVPTree(substring(x, child + 1), indent + 1)
    }
    if (sibling > 0 && sibling < end && (child < 0 || sibling < child)) {
        cat(paste0(paste(rep("  ", indent), collapse=""), 
                   substr(x, 1, sibling - 1), "\n"))
        formatVPTree(substring(x, sibling + 2), indent)
    }
}

【讨论】:

  • 太棒了!我正在尝试自动执行此操作,但似乎无法将 formatVPTree(current.vpTree()) 的输出写入列表;它只是打印到控制台。任何想法如何做到这一点?
  • 没关系,我确信有更好的方法,但我发现 capture.output(formatVPTree(current.vpTree())) 有效,我只需要修剪空白
  • 我添加了一些代码,将使用正则表达式搜索所需的视口名称。
【解决方案2】:

使用带有 element_markdown 的 html 标签,您可以在图例中指定任何您想要的内容。

假设你在一个文件中有一个png图片,这个文件位于某个folder,文件名为image,那么你可以运行,例如:

p = ggplot(mtcars, aes(mpg, disp, colour = factor(vs))) + 
    geom_point() +
    theme(legend.key.size = unit(1, "cm"))
labels <- c()
labels[1]=paste0("<img src='", folder, image, ".png' width='16' />")
labels[2]="<strong>Faces</strong>"
p + theme(legend.text = element_markdown(color = "black", size = 11)) + 
scale_color_manual(name = "factor(vs)", labels = labels, , values = c(1,2))

将返回:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    相关资源
    最近更新 更多