library(ggplot2)library(ggrepel)p <-ggplot(mtcars,aes(wt, mpg, label =rownames(mtcars), colour =factor(cyl))) +geom_point() +geom_text_repel(seed =1)# Not available at `ggplot_build()` - x/y pos is untransformed data valuesidentical(unlist(mtcars[, c("wt", "mpg")], use.names =FALSE),unlist(layer_data(p, 2L)[, c("x", "y")], use.names =FALSE))
[1] TRUE
# Not available at `ggplot_gtable()` - no labels materialized within layerlayer_grob(p, 2L)[[1]]$children
()
# IS available at `grid.draw()`, upon evaluation of `ggrepel:::makeContent.textrepeltree()`# - need some extra work to get the materialized grobs with `grid.force()` and `grid.get()`library(grid)plot(p)grid.force()
# These hold the npc coordinate valuesrepel_grob$children$textrepelgrob15$x
[1] sum(0.873703844920667native, 0char, 0char)
# The ggrepel grob stores info from data after `ggplot_build()`, so you can# cross-check that to recover what element corresponds to which row in datais.data.frame(repel_grob$data)
ggplot(mtcars,aes(wt, mpg, label =rownames(mtcars), colour =factor(cyl))) +geom_point() +geom_text(aes(x =I(x), y =I(y), label = label, color =I(colour)),data = repel_df )
Source Code
---title: "ggrepel positions"format: html: code-tools: trueexecute: warning: false---```{r}library(ggplot2)library(ggrepel)p <-ggplot(mtcars,aes(wt, mpg, label =rownames(mtcars), colour =factor(cyl))) +geom_point() +geom_text_repel(seed =1)# Not available at `ggplot_build()` - x/y pos is untransformed data valuesidentical(unlist(mtcars[, c("wt", "mpg")], use.names =FALSE),unlist(layer_data(p, 2L)[, c("x", "y")], use.names =FALSE))# Not available at `ggplot_gtable()` - no labels materialized within layerlayer_grob(p, 2L)[[1]]$children``````{r}# IS available at `grid.draw()`, upon evaluation of `ggrepel:::makeContent.textrepeltree()`# - need some extra work to get the materialized grobs with `grid.force()` and `grid.get()`library(grid)plot(p)grid.force()x <-grid.ls()repel_grob_nm <-grep(x = x$name, "textrepeltree", value =TRUE)repel_grob_nmrepel_grob <-grid.get(repel_grob_nm)# Drawn labels available for inspection from the `<forcedgrob>`repel_grob$children# These hold the npc coordinate valuesrepel_grob$children$textrepelgrob15$x# The ggrepel grob stores info from data after `ggplot_build()`, so you can# cross-check that to recover what element corresponds to which row in datais.data.frame(repel_grob$data)``````{r}# Example of recoveryrepel_pos <- repel_grob$children |>Filter(x = _, \(g) grepl(x = g$name, "textrepelgrob")) |>lapply(\(g) sapply(g[c("x", "y")], convertUnit, "native", valueOnly =TRUE)) |>do.call(rbind, args = _) |> tibble::as_tibble(rownames ="textid")repel_pos_data <- repel_grob$data[as.integer(gsub(x = repel_pos$textid, "textrepelgrob", "")), c("label", "colour") # size, alpha, ...]repel_df <-cbind(repel_pos, repel_pos_data)repel_df``````{r}ggplot(mtcars,aes(wt, mpg, label =rownames(mtcars), colour =factor(cyl))) +geom_point() +geom_text(aes(x =I(x), y =I(y), label = label, color =I(colour)),data = repel_df )```