ggplot2에서 geom_point의 npc 좌표


10

어떻게 얻을 수 (X)를 , Y (A)의 좌표 geom_point을 A의 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")

이것은 다음을 제공합니다.

여기에 이미지 설명을 입력하십시오

(A) 내로 이것을 변환함으로써 GROB , I는 이것에 대해 일부 추가 정보를 추출 할 수 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()축에 영향을 미치고 또한 전체 플롯 이미지에 대한 점의 위치를 이동합니다.

업데이트 : 축의 글꼴 크기가 플롯의 너비와 높이에 따라 플롯 패널 의 상대적 크기에 영향을 미친다는 것을 알았습니다 . 따라서 plot widthplot height를 정의하지 않고 npc 단위로 위치를 제공하는 것은 쉬운 일이 아닙니다 . 가능한 경우 geom_points 의 위치를 플롯 폭플롯 높이 의 함수로 지정하십시오 .


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

reprex 패키지 (v0.3.0)로 2020-03-25에 작성


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)]))의 높이의 합입니다.
Allan Cameron

@LBogaardt 나는 간결함과 명료 함 사이의 균형을 잡으려고했지만 아마도이 점을 제대로 이해하지 못했을 것입니다.
Allan Cameron

아, 그래서 ggplot은 테이블과 같습니다. 하나는 y- 레이블, 하나는 y- 축 번호 매기기 등을위한 것입니다. 각 행은 너비 / 높이를가집니다. 이 표에서 패널은 하나의 셀입니까? 알았다. 고마워 앨런.
LBogaardt

1
정확하게 @LBogaardt. 실제로 ggplotGrob는 gTable 또는 grob 테이블을 생성합니다
Allan Cameron
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.