Add rectangles around common values โ€‹โ€‹in ggplot

When I create a pilot project, I use ggplot to display the layout. Here is a simple example:

df <- data.frame(Block=rep(1:2, each=18), Row=rep(1:9, 4), Col=rep(1:4, each=9), Treat=sample(c(1:6),replace=F)) 

What will I build, like:

 df.p <- ggplot(df, aes(Row, Col)) + geom_tile(aes(fill=as.factor(Treat))) 

:

design

Sometimes I have a structure inside the design that I would like to highlight by placing a box around it, for example, the main bar. In this case:

 df$Mainplot <- ceiling(df$Row/3) + 3*(ceiling(df$Col/2) - 1) 

Then I use geom_rect and some messy code that needs to be set up for each project to create something like:

designwithmainplot

Question: How to add rectangles around the main graphs in a simple way? This seems like a pretty simple problem, but I did not find the obvious way. I can display color or some other aesthetics in mainplot, but I can not surround them with a box. Any pointers are very appreciated.

+6
source share
3 answers

Here is a possible solution where I create a helper data.frame to build borders with geom_rect() . I'm not sure that it is as simple as we would like! I hope that the code that calculates the coordinates of the rectangle will be reused / generalized with a little extra effort.

 library(ggplot2) # Load example data. df = data.frame(Block=rep(1:2, each=18), Row=rep(1:9, 4), Col=rep(1:4, each=9), Treat=sample(c(1:6),replace=F)) df$Mainplot = ceiling(df$Row/3) + 3*(ceiling(df$Col/2) - 1) # Create an auxiliary data.frame for plotting borders. group_dat = data.frame(Mainplot=sort(unique(df$Mainplot)), xmin=0, xmax=0, ymin=0, ymax=0) # Fill data.frame with appropriate values. for(i in 1:nrow(group_dat)) { item = group_dat$Mainplot[i] tmp = df[df$Mainplot == item, ] group_dat[i, "xmin"] = min(tmp$Row) - 0.5 group_dat[i, "xmax"] = max(tmp$Row) + 0.5 group_dat[i, "ymin"] = min(tmp$Col) - 0.5 group_dat[i, "ymax"] = max(tmp$Col) + 0.5 } p2 = ggplot() + geom_tile(data=df, aes(x=Row, y=Col, fill=factor(Treat)), colour="grey30", size=0.35) + geom_rect(data=group_dat, aes(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax), size=1.4, colour="grey30", fill=NA) ggsave(filename="plot_2.png", plot=p2, height=3, width=6.5) 

enter image description here

+4
source

Here is a solution that could be simpler. Just use geom_tile with an alpha setting of 0. I did not find the time to give you an exact solution, but here is an example. To achieve what you want, I assume that you will need to create a new data frame that should be fairly simple.

 df <- data.frame(Block=rep(1:2, each=18),Row=rep(1:9, 4),Col=rep(1:4, each=9),Treat=sample(c(1:6),replace=F)) df$blocking <- rep(sort(rep(1:3,3)),4) df.p <- ggplot(df, aes(Row, Col)) + geom_tile(aes(fill=as.factor(Treat))) df.p+ geom_tile(data=df,aes(x=Row,y=blocking),colour="black",fill="white",alpha=0,lwd=1.4) 

alpha=0 will create an empty fragment, and then you can set the line width with lwd . This is probably simpler than specifying all the rectangles. Hope this helps.

+2
source

I thought it was worth publishing my own (imperfect) solution, as it seems that nothing obvious is missing to me. I'm going to leave the question unanswered in the hope that someone will come up with something.

I am currently using geom_rect in a way that could probably be shared (perhaps in addition to geom_border to ggplot?). For example, in my question, the basic information is that each main plan is 3 x 2.

Adding the original question on df.p , this is what I am doing now:

 df.p1 <- df.p + geom_rect(aes(xmin=((Mainplot- 3*(ceiling(Col/2)-1) )-1)*3 + 0.5, xmax=((Mainplot - 3*(ceiling(Col/2)-1))-1)*3 + 3.5, ymin=ceiling(ceiling(Col/2)/2 + 2*(ceiling(Col/2)-1))-0.5, ymax=2*ceiling(Col/2)+0.5), colour="black", fill="transparent",size=1) 

Ugly, I know - that is the question. This code generates a second plot from the question. Perhaps the best option is to create this in a function.

0
source

All Articles