Reputation: 131
I want to create Scatter Plot Matrix using ggplot2. Partially I coped with my problem. I managed to create three-part graph using ggplot2: the lower triangle - Scatterplot, diagonally - variable names and the upper triangle - correlation coefficient (R^2). Below I give piece of my data + code generating my chart. My data:
f =
C xval V yval corr V1
1 1622 1 1622 1 2ng
1 1622 2 1639 0.997 2ng
1 1622 3 1584 0.992 2ng
1 1622 4 1549 0.99 2ng
1 1622 5 1541 0.993 2ng
1 1622 6 1543 0.994 2ng
1 1622 7 1530 0.988 2ng
2 1639 1 1622 0.997 5ng
2 1639 2 1639 1 5ng
2 1639 3 1584 0.997 5ng
2 1639 4 1549 0.997 5ng
2 1639 5 1541 0.998 5ng
2 1639 6 1543 0.998 5ng
2 1639 7 1530 0.995 5ng
3 1584 1 1622 0.992 10ng
3 1584 2 1639 0.997 10ng
3 1584 3 1584 1 10ng
3 1584 4 1549 0.997 10ng
3 1584 5 1541 0.995 10ng
3 1584 6 1543 0.999 10ng
3 1584 7 1530 0.999 10ng
4 1549 1 1622 0.99 15ng
4 1549 2 1639 0.997 15ng
4 1549 3 1584 0.997 15ng
4 1549 4 1549 1 15ng
4 1549 5 1541 0.998 15ng
4 1549 6 1543 0.998 15ng
4 1549 7 1530 0.998 15ng
5 1541 1 1622 0.993 30ng
5 1541 2 1639 0.998 30ng
5 1541 3 1584 0.995 30ng
5 1541 4 1549 0.998 30ng
5 1541 5 1541 1 30ng
5 1541 6 1543 0.998 30ng
5 1541 7 1530 0.995 30ng
6 1543 1 1622 0.994 60ng
6 1543 2 1639 0.998 60ng
6 1543 3 1584 0.999 60ng
6 1543 4 1549 0.998 60ng
6 1543 5 1541 0.998 60ng
6 1543 6 1543 1 60ng
6 1543 7 1530 0.998 60ng
7 1530 1 1622 0.988 100ng
7 1530 2 1639 0.995 100ng
7 1530 3 1584 0.999 100ng
7 1530 4 1549 0.998 100ng
7 1530 5 1541 0.995 100ng
7 1530 6 1543 0.998 100ng
7 1530 7 1530 1 100ng
And code:
g <- ggplot(data = f, aes(x=xval, y=yval))+
geom_point(data = f[(xtfrm(f$C)<xtfrm(f$V)),], colour = "darkblue", size = 1.5)+
geom_smooth(data = f[(xtfrm(f$C)<xtfrm(f$V)),], aes(colour = "red"), method="lm", size = 0.1)+
geom_text(data = f[(xtfrm(f$C)==xtfrm(f$V)),], aes(x = 4000, y = 4000, label = paste(V1)), size = 10, colour="red")+
geom_tile(aes(fill=corr))+
geom_text(data = f[(xtfrm(f$C)>xtfrm(f$V)), ], aes(x = 4000, y = 4000, label = corr), size = 10)+
coord_cartesian(xlim=c(0,8000), ylim=c(0,8000))+
facet_grid(V~C, space = "fixed") +
theme(panel.grid.major = element_blank(), strip.background = element_blank(), strip.text.y = element_blank(), strip.text.x = element_blank(), legend.position = "none")
g
However, I have got a problem for improving the appearance of the graph. I want to separate part of the graph with different background colour for example: white background for scatters, gray for variable names and blue for correlation coeff. Does anyone know how to do it? Is it possible or I have to create each part of graph separately?
Upvotes: 4
Views: 2067
Reputation: 93771
One way to do this is to create each plot separately and then lay them out together. This allows you to set all the plot elements independently for each plot, including theme elements like the background fill color.
The function below uses mapply
to create a separate plot for each combination of V
and C
, and uses if
statements to assign the desired background color for each plot.
library(gridExtra)
p.list = mapply(FUN=function(v,c) {
fvc = f[f$V==v & f$C==c, ]
g <- ggplot(data=fvc, aes(x=xval, y=yval))+
coord_cartesian(xlim=c(0,8000), ylim=c(0,8000))+
theme(axis.title=element_blank(),
axis.text=element_text(size=8))
if (c == v) {
g = g + geom_text(aes(x = 4000, y = 4000, label=V1),
size = 6, colour="red")
}
if (c < v) {
g = g + geom_text(aes(x = 4000, y = 4000, label=corr), size = 6) +
theme(panel.background=element_rect(fill=hcl(180,100,60, alpha=0.3)))
}
if (c > v) {
g = g + geom_point(colour = "darkblue", size = 1.5) +
geom_smooth(aes(colour = "red"), method="lm", size = 0.1) +
theme(panel.background=element_blank(),
panel.grid.major=element_line(colour="grey80", size=0.3))
}
if(v != 1) {
g = g + theme(axis.text.y=element_blank(),
axis.ticks.y=element_blank())
}
if(c != max(f$C)) {
g = g + theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank())
}
return(g) },
expand.grid(V=unique(f$V), C=unique(f$C))[[1]],
expand.grid(V=unique(f$V), C=unique(f$C))[[2]], SIMPLIFY=FALSE)
Now lay out all the plots together and add x-axis and y-axis labels:
grid.arrange(
arrangeGrob(
arrangeGrob(textGrob("Y vals", rot=90),
do.call(arrangeGrob, c(p.list, ncol=7)), widths=c(0.05,0.95)),
textGrob("X vals"), heights=c(0.95,0.05)))
As you can see in the above plot, there's one remaining issue: The panels in the first column and last row have a smaller plot area, due to the axis labels. This SO answer shows how to equalize the sizes of the plot areas, but you have to list each plot object separately.
Fortunately, we don't have to roll our own function to equalize the size of all the plot areas in a large grid of plots, as plot_grid
from the cowplot
package, can do this. However, I thought the margins between each graph were too large after running plot_grid
. You can tweak this by changing the plot margins when you create the graphs. To do this, you can adjust the plot margins in the return
line of the plotting function as follows:
return(g + theme(plot.margin=unit(c(0,-0.15,0,-0.15), "lines"))) },
Then plot using plot_grid
:
library(cowplot)
grid.arrange(
arrangeGrob(
arrangeGrob(textGrob("Y vals", rot=90),
do.call(plot_grid, c(p.list, align="hv")), widths=c(0.05,0.95)),
textGrob("X vals"), heights=c(0.95,0.05)))
Upvotes: 7