Подтвердить что ты не робот

Добавить прозрачное окно/замочную скважину ggplot2 (сетка)

Иногда полезно использовать технику добавления серого полупрозрачного слоя к изображению, а затем разрезать замочную скважину на этот слой, чтобы выделить определенную часть изображения ниже. Ниже приведен пример из youtube vide:

enter image description here

Я делаю это с сюжетами иногда, но использую Inkscape для добавления полупрозрачного слоя, а затем использую ластик, чтобы вырезать отверстие в этом слое. Это (а) выглядит менее профессиональным (б) требует дополнительного времени и отдельной программы и (в) возможной потери качества.

Я хочу сделать это в R. Я спрашиваю о ggplot2, потому что это мой инструмент выбора, но я думаю, что любой ответ на сетку был бы хорошим (я знаю, что база, вероятно, имеет совсем другой подход).

Итак, вот MWE, где я добавил geom_rect, чтобы показать, где мы хотим вырезать замочную скважину/окно:

ggplot(mtcars, aes(mpg, wt)) + 
    geom_point(size=3) +    
    geom_rect(mapping=aes(xmin=20, xmax=25, 
        ymin=3, ymax=3.3), color="black", alpha=.01)

Как я могу использовать R для создания графика, который выглядит примерно так:

enter image description here

4b9b3361

Ответ 1

Оказывается, вы можете сделать это с помощью grid.path(...) в пакете grid. Прочтите документацию, чтобы узнать, как создать путь с отверстием в нем.

library(gridExtra)
library(ggplot2)

ggp <- ggplot(mtcars, aes(mpg, wt)) + geom_point(size=3)
grid.newpage()
grid.draw(arrangeGrob(ggp))
grid.path(c(0,0,1,1,.48,.48,.62,.62),
                    c(0,1,1,0,.43,.50,.50,.43),
                    id=rep(1:2, each=4),
                    rule="evenodd",gp=gpar(fill="black", alpha=0.6))

NB: grid.draw(...) и grid.path(...) находятся в пакете grid; arrangeGrob(...) находится в пакете gridExtra. Загрузка gridExtra вызывает загрузку grid. Спасибо @MartinBel за предложение отредактировать.

В ответ на комментарий @BrandonBertelsen: grid.path(...) агностик о форме; вам просто нужно предоставить координаты.

center <- c(x=0.55,y=0.48)
r      <- 0.1
circle <- do.call(rbind,lapply(seq(0,2*pi,length=36),
                               function(th)c(x=r*cos(th),y=r*sin(th))))
circle <- data.frame(circle)
circle$x <- circle$x + center["x"]
circle$y <- circle$y + center["y"]

ggp <- ggplot(mtcars, aes(mpg, wt)) + geom_point(size=3)
grid.newpage()
grid.draw(arrangeGrob(ggp))
grid.path(c(0,0,1,1,circle[,1]),
          c(0,1,1,0,circle[,2]),
          id=c(1,1,1,1,rep(2,nrow(circle))),
          rule="evenodd",gp=gpar(fill="black", alpha=0.6))

"Круг" представляет собой эллипс из-за соотношения сторон окна графика.


Дополнительная литература: Не то, что вы рисуете, ее то, что вы не рисуете Пол Мурелл в журнале R

Ответ 2

Как насчет следующего?

P <- ggplot(mtcars, aes(mpg, wt)) + geom_point(size=3) 

## Set the limits for x & y
xlims <- c(20, 25)
ylims <- c(3, 3.3)


# Where P is the original plot
P + geom_rect(mapping=aes(xmin=-Inf, xmax=min(xlims), ymin=-Inf, ymax=+Inf), fill="black", alpha=.01) +
    geom_rect(mapping=aes(xmin=min(xlims), xmax=+Inf, ymin=max(ylims), ymax=+Inf), fill="black", alpha=.01) +
    geom_rect(mapping=aes(xmin=min(xlims), xmax=+Inf, ymin=-Inf, ymax=min(ylims)), fill="black", alpha=.01) +
    geom_rect(mapping=aes(xmin=max(xlims), xmax=+Inf, ymin=min(ylims), ymax=max(ylims)), fill="black", alpha=.01) 

enter image description here

Ответ 3

require(ggplot2)

#represent some tiles based on your axes (10 x 10, by 1) deoending on resolution you want
alpha_tiles<-expand.grid(x=0:10,y=0:10,a=0.6)

#set alpha to 0 for the coordinate
alpha_tiles[alpha_tiles$x %in% 7:9 & alpha_tiles$y==7,]$a<-0

qplot(0:10,0:10, size=10, color="red") + theme_bw() +
  geom_raster(data=alpha_tiles,aes(x=x,y=y), alpha=alpha_tiles$a, fill="grey")

enter image description here

или это для более полного ответа, который затушевывает весь сюжет:

require(ggplot2)

#represent some tiles based on your axes (here 100 x 100, by 1) depending on resolution you want
resolution<-100
alpha_tiles<-expand.grid(x=0:resolution,y=0:resolution,a=0.6)

#set alpha to 0 for the coordinates to highlight
alpha_tiles[alpha_tiles$x %in% 40:70 & alpha_tiles$y %in% 70:80,]$a<-0
alpha_tiles[alpha_tiles$x %in% 10:30 & alpha_tiles$y %in% 10:25,]$a<-0

p<-qplot(0:10,0:10, size=10, color="red") + theme_bw() # background plot


qplot(0:resolution,0:resolution,geom="blank") + theme(axis.line=element_blank(),
                                     axis.text.x=element_blank(),
                                     axis.text.y=element_blank(),
                                     axis.ticks=element_blank(),
                                     axis.title.x=element_blank(),
                                     axis.title.y=element_blank(),
                                     legend.position="none",
                                     panel.background=element_blank(),
                                     panel.border=element_blank(),
                                     panel.grid.major=element_blank(),
                                     panel.grid.minor=element_blank(),
                                     plot.background=element_blank()) +
  annotation_custom(ggplotGrob(p),0,resolution,0,resolution) +
geom_raster(data=alpha_tiles,aes(x=x,y=y), alpha=alpha_tiles$a, fill="grey")

enter image description here