coordinate npc di geom_point in ggplot2


10

Come posso ottenere le coordinate x , y di un geom_point in un ggplot , dove la cornice di riferimento è l'intera immagine tracciata?

Posso creare un ggplot con alcuni geom_point usando:

library(ggplot2)

my.plot <- ggplot(data.frame(x = c(0, 0.456, 1), y = c(0, 0.123, 1))) +
             geom_point(aes(x, y), color = "red")

Questo da:

inserisci qui la descrizione dell'immagine

Convertendo questo in un grob , posso estrarre alcune informazioni aggiuntive su questo ggplot , come le coordinate rispetto al pannello della trama, contrassegnato dalla freccia viola. Tuttavia, questo ignora lo spazio occupato dagli assi.

my.grob <- ggplotGrob(my.plot)
my.grob$grobs[[6]]$children[[3]]$x
# [1] 0.0454545454545455native 0.46native 0.954545454545454native 
my.grob$grobs[[6]]$children[[3]]$y
# [1] 0.0454545454545455native 0.157272727272727native 0.954545454545454native

Come posso ottenere i valori delle coordinate x , y quando inizio a misurare dall'angolo in basso a sinistra dell'intera immagine, contrassegnato dalla freccia verde?

Se è possibile, vorrei che la soluzione prendesse in considerazione il tema di ggplot . L'aggiunta di un tema come + theme_void()influisce sugli assi e sposta anche la posizione dei punti rispetto all'intera immagine tracciata.

Aggiornamento : mi sono reso conto che la dimensione del carattere degli assi cambia a seconda della larghezza e dell'altezza della trama, influenzando la dimensione relativa del pannello della trama . Quindi non sarà banale fornire la posizione in unità npc senza definire la larghezza e l' altezza della trama . Se possibile, indicare la posizione dei geom_points in funzione della larghezza e dell'altezza della trama .


5
Perché 2 downvotes?
markus

2
Sì, si prega di commentare se avete dubbi o suggerimenti.
LBogaardt,

1
Considera che il grafico stesso non ha dimensioni fisse: le posizioni dei punti assoluti non dipendono solo dalle dimensioni del dispositivo su cui stampi, ma anche dal rapporto degli assi. Quindi abbastanza curioso di cosa ti serva
Tjebo

1
Per quanto riguarda i downvotes, nota che non ho bisogno di giustificare la mia domanda perché sia ​​una domanda valida su SE. Perché voglio sapere? Perché faccio.
LBogaardt,

1
anche questo. ma non ha mai avuto una vera risposta stackoverflow.com/questions/48710478/...
Tjebo

Risposte:


5

Quando ridimensionate un ggplot, la posizione degli elementi all'interno del pannello non si trova in posizioni fisse nello spazio npc. Questo perché alcuni dei componenti della trama hanno dimensioni fisse e alcuni (ad esempio il pannello) cambiano le dimensioni in base alle dimensioni del dispositivo.

Ciò significa che qualsiasi soluzione deve tenere conto delle dimensioni del dispositivo e, se si desidera ridimensionare il grafico, è necessario eseguire nuovamente il calcolo. Detto questo, per la maggior parte delle applicazioni (incluso il tuo, dal suono delle cose), questo non è un problema.

Un'altra difficoltà è assicurarsi di identificare i grobs corretti all'interno del pannello grob, ed è difficile vedere come questo possa essere facilmente generalizzato. L'uso delle funzioni del sottoinsieme elenco [[6]]e [[3]]nel tuo esempio non è generalizzabile ad altri grafici.

Ad ogni modo, questa soluzione funziona misurando le dimensioni e la posizione del pannello all'interno del frontone e convertendo tutte le dimensioni in millimetri prima di dividere le dimensioni del grafico in millimetri per convertirle in spazio npc. Ho cercato di renderlo un po 'più generale estraendo il pannello e i punti per nome anziché per indice numerico.

library(ggplot2)
library(grid)
require(gtable)

get_x_y_values <- function(gg_plot)
{
  img_dim      <- grDevices::dev.size("cm") * 10
  gt           <- ggplot2::ggplotGrob(gg_plot)
  to_mm        <- function(x) grid::convertUnit(x, "mm", valueOnly = TRUE)
  n_panel      <- which(gt$layout$name == "panel")
  panel_pos    <- gt$layout[n_panel, ]
  panel_kids   <- gtable::gtable_filter(gt, "panel")$grobs[[1]]$children
  point_grobs  <- panel_kids[[grep("point", names(panel_kids))]]
  from_top     <- sum(to_mm(gt$heights[seq(panel_pos$t - 1)]))
  from_left    <- sum(to_mm(gt$widths[seq(panel_pos$l - 1)]))
  from_right   <- sum(to_mm(gt$widths[-seq(panel_pos$l)]))
  from_bottom  <- sum(to_mm(gt$heights[-seq(panel_pos$t)]))
  panel_height <- img_dim[2] - from_top - from_bottom
  panel_width  <- img_dim[1] - from_left - from_right
  xvals        <- as.numeric(point_grobs$x)
  yvals        <- as.numeric(point_grobs$y)
  yvals        <- yvals * panel_height + from_bottom
  xvals        <- xvals * panel_width + from_left
  data.frame(x = xvals/img_dim[1], y = yvals/img_dim[2])
}

Ora possiamo provarlo con il tuo esempio:

my.plot <- ggplot(data.frame(x = c(0, 0.456, 1), y = c(0, 0.123, 1))) +
             geom_point(aes(x, y), color = "red")

my.points <- get_x_y_values(my.plot)
my.points
#>           x         y
#> 1 0.1252647 0.1333251
#> 2 0.5004282 0.2330669
#> 3 0.9479917 0.9442339

E possiamo confermare che questi valori sono corretti disegnando alcuni grobs di punti sui tuoi punti rossi, usando i nostri valori come coordinate npc:

my.plot
grid::grid.draw(pointsGrob(x = my.points$x, y = my.points$y, default.units = "npc"))

Creato il 25-03-2010 dal pacchetto reprex (v0.3.0)


1
Questa sum(to_mm(gt$heights[seq(panel_pos$t - 1)]))parte è la più strana. Potresti spiegare cosa stai riassumendo qui?
LBogaardt,

1
@LBogaardt panel_pos$tfornisce la riga della griglia in cui si trova il pannello (flessibile), quindi seq(panel_pos$t -1)tutti i numeri di riga sopra questo, e quindi sum(to_mm(gt$heights[seq(panel_pos$t - 1)]))la somma delle altezze di queste righe.
Allan Cameron,

@LBogaardt Stavo cercando di trovare un equilibrio tra brevità e chiarezza, ma forse non ho capito bene ...
Allan Cameron,

Ah, quindi un ggplot è come una tabella, con una colonna per l'etichetta y, una per la numerazione dell'asse y ecc. Allo stesso modo per le righe, ciascuna con larghezza / altezza. Il pannello è una cella in questa tabella? Fatto. Grazie Allan.
LBogaardt,

1
Esatto, @LBogaardt. In effetti, ggplotGrob produce un tavolo gTable o grob
Allan Cameron,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.