npc координати geom_point у ggplot2


10

Як я можу отримати координати x , y гео-точки в ggplot , де опорний кадр - це все накреслене зображення?

Я можу створити ggplot за допомогою деяких geom_point , використовуючи:

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")

Це дає:

введіть тут опис зображення

Перетворюючи це в могилу , я можу отримати деяку додаткову інформацію про цей ggplot , як координати стосовно панелі сюжету, позначеної фіолетовою стрілкою. Однак це ігнорує простір, зайнятий осями.

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

Як я можу отримати значення координат x , y, коли починаю вимірювати з лівого нижнього кута всього зображення, позначеного зеленою стрілкою?

Якщо це можливо, я хотів би рішення , щоб прийняти до уваги тему про ggplot . Додавання теми на зразок + theme_void()впливає на осі, а також змінює розташування точок відносно всього накресленого зображення.

Оновлення : я зрозумів, що розмір шрифту осей змінюється залежно від ширини та висоти ділянки, впливаючи на відносний розмір панелі ділянки . Тож не буде тривіальним вказати розташування в npc- одиницях, не визначаючи ширину ділянки та висоту ділянки . Якщо можливо, вкажіть розташування гео-точок як функцію від ширини ділянки та висоти ділянки .


5
Чому 2 потік?
Маркус

2
Так, будь ласка, коментуйте, якщо у вас є проблеми чи пропозиції.
LBogaardt

1
Врахуйте, що сам сюжет не має фіксованих розмірів - абсолютні точки точок залежать не тільки від розміру пристрою, на який ви друкуєте, але і від співвідношення ваших осей. Тому досить цікаво, для чого це потрібно
Tjebo

1
Щодо низових запитів, зауважте, що мені не потрібно обґрунтовувати своє питання, щоб воно було дійсним питанням щодо SE. Чому я хочу знати? Тому що я.
LBogaardt

1
цей теж. але ніколи не отримав реальний відповідь stackoverflow.com/questions/48710478 / ...
Tjebo

Відповіді:


5

Коли ви змінюєте розмір ggplot, положення елементів на панелі не знаходяться у фіксованих положеннях у просторі npc. Це пояснюється тим, що деякі компоненти ділянки мають фіксовані розміри, а деякі з них (наприклад, панель) змінюють розміри відповідно до розмірів пристрою.

Це означає, що будь-яке рішення повинно враховувати розмір пристрою, і якщо ви хочете змінити розмір графіку, вам доведеться запустити обчислення ще раз. Сказавши, що для більшості програм (включаючи і ваші, звуки речей) це не проблема.

Ще одна складність полягає в тому, щоб переконатися, що ви виявите правильні грони в могилі панелі, і важко зрозуміти, як це можна легко узагальнити. Використання функцій підмножини списку [[6]]та [[3]]у вашому прикладі не можна узагальнити для інших графіків.

У будь-якому випадку це рішення працює, вимірюючи розмір та положення панелі всередині gtable та перетворюючи всі розміри в міліметри, перш ніж ділити на розміри ділянки в міліметри, щоб перетворити на простір npc. Я спробував зробити це трохи більш загальним, витягуючи панель і точки по імені, а не числовий індекс.

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])
}

Тепер ми можемо перевірити це на вашому прикладі:

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

І ми можемо підтвердити, що ці значення є правильними, побудувавши кілька крапок над вашими червоними точками, використовуючи наші значення як координати npc:

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

Створено 2020-03-25 пакетом reprex (v0.3.0)


1
Ця sum(to_mm(gt$heights[seq(panel_pos$t - 1)]))частина є найдивнішою. Чи можете ви пояснити, що ви тут підсумовуєте?
LBogaardt

1
@LBogaardt panel_pos$tдає ряд сітки, в якій сидить (гнучка) панель, так seq(panel_pos$t -1)само всі номери рядків вище цього, а отже sum(to_mm(gt$heights[seq(panel_pos$t - 1)])), і сума висот цих рядків.
Аллан Камерон

@LBogaardt Я намагався досягти балансу між стислістю та ясністю, але, мабуть, я не зовсім зрозумів це право ...
Аллан Камерон,

Так, ggplot - це як таблиця, з одним стовпцем для y-мітки, один для нумерації осі y тощо. Так само, як для рядків, кожен з шириною / висотою. Панель - одна клітинка цієї таблиці? Зрозумів. Дякую Аллан.
LBogaardt

1
Саме так, @LBogaardt. Насправді ggplotGrob створює таблицю gTable, або grob,
Аллан Камерон,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.