【问题标题】:How do you relate ggplot2 grobs back to the data?你如何将 ggplot2 grobs 与数据联系起来?
【发布时间】:2012-01-23 13:47:59
【问题描述】:

给定一个 ggplot,例如点,你将如何找出给定点对应的数据行?

示例图:

library(ggplot2)
(p <- ggplot(mtcars, aes(mpg, wt)) +
    geom_point() +
    facet_wrap(~ gear)
)

我们可以通过grid.ls + grid.get 获得包含点的grobs。

grob_names <- grid.ls(print = FALSE)$name
point_grob_names <- grob_names[grepl("point", grob_names)]
point_grobs <- lapply(point_grob_names, grid.get)

最后一个变量包含 x-y 坐标和点大小等的详细信息(尝试unclass(point_grobs[[1]])),但我如何获得每个点对应的mtcars 中的数据行并不明显。


为了回答 kohske 关于我为什么要这样做的问题,我使用 gridSVG 创建了一个交互式散点图。当您将鼠标滚动到一个点上时,我想显示上下文信息。在 mtcars 示例中,我可以显示带有汽车名称或数据框该行中的其他值的工具提示。

到目前为止,我的 hacky 想法是包含一个 id 列作为不可见的文本标签:

mtcars$id <- seq_len(nrow(mtcars))
p + geom_text(aes(label = id), colour = NA)

然后从点 grob 到文本 grob 遍历 grobs 树,并显示 label 索引的数据集的行。

这是繁琐的,不是很普遍。如果有办法将 id 值存储在点 grob 中,它会更干净。

【问题讨论】:

  • 不容易。你的最终目标是什么?可能还有其他选择。
  • @kohske:评论太长了,所以我更新了问题来解释我在做什么。
  • 非常有趣。我明白你的目的。不幸的是,我们无法通过 grob 访问数据(甚至可能在下一个版本中)。但也许拥有有关数据的信息会很有用(尤其是当 `stat = "identity" 时)。我会讨论的。
  • 还有一些技术问题是ggplot2支持一个面板上的多个数据。因此,id 可能不足以识别数据行。

标签: r ggplot2 r-grid


【解决方案1】:

此脚本会生成一个 SVG 文件,您可以在其中交互式地注释这些点。

library(ggplot2)
library(gridSVG)

geom_point2 <- function (...) GeomPoint2$new(...)
GeomPoint2 <- proto(GeomPoint, {
  objname <- "point2"
  draw <- function(., data, scales, coordinates, na.rm = FALSE, ...) {
   data <- remove_missing(data, na.rm, c("x", "y", "size", "shape"), 
        name = "geom_point")
    if (empty(data)) 
        return(zeroGrob())
    name <- paste(.$my_name(), data$PANEL[1], sep = ".")
    with(coordinates$transform(data, scales), ggname(name,
        pointsGrob(x, y, size = unit(size, "mm"), pch = shape, 
            gp = gpar(col = alpha(colour, alpha), fill = fill, label = label,
                fontsize = size * .pt))))
  }}
  )

p <- ggplot(mtcars, aes(mpg, wt, label = rownames(mtcars))) + geom_point2() + facet_wrap(~ gear)
print(p)

grob_names <- grid.ls(print = FALSE)$name
point_grob_names <- sort(grob_names[grepl("point", grob_names)])
point_grobs_labels <- lapply(point_grob_names, function(x) grid.get(x)$gp$label)

library(rjson)
jlabel <- toJSON(point_grobs_labels)

grid.text("value", 0.05, 0.05, just = c(0, 0), name = "text_place", gp = gpar(col = "red"))

script <- '
var txt = null;
function f() {
    var id = this.id.match(/geom_point2.([0-9]+)\\.points.*\\.([0-9]+)$/);
    txt.textContent = label[id[1]-1][id[2]-1];
}

window.addEventListener("load",function(){
    var es = document.getElementsByTagName("circle");
    for (i=0; i<es.length; ++i) es[i].addEventListener("mouseover", f, false);

    txt = (document.getElementById("text_place").getElementsByTagName("tspan"))[0];

},false);
'

grid.script(script = script)
grid.script(script = paste("var label = ", jlabel))

gridToSVG()

你知道我可以上传 SVG 文件的地方吗?

【讨论】:

  • 太棒了!不过,我必须删除 filename = "s.js" 参数才能让它为我工作。
  • 我很欣赏这是旧的,但我收到错误 Error in eval(expr, envir, enclos) : could not find function "proto"。这是版本问题吗?
  • 也许你需要library(proto),不过我没有测试。
  • 我遇到了同样的错误,我添加了library(proto)library(grid)library(scales),并将GeomPoint 替换为ggplot2:::GeomPointpointsGrobgrid:::pointsGrobzeroGrob 与@ 987654333@,这可能对一些人有所帮助,但最终还是以Error: attempt to apply non-function...
  • 不,它不起作用! Error in proto(GeomPoint, { : object 'GeomPoint' not found Execution halted
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多