Flat polyhedral matrices in facets with different xy axis

I collected data from a set of online forums and wanted to build, using ggplot and facets (one facet per forum), a matrix showing how many times user A answered user B.

Here is the code to download the toy example:

library(ggplot2) library(dplyr) df.edges <- data.frame(from = c('forum1_user1', 'forum1_user1', 'forum1_user2', 'forum1_user2', 'forum2_user1', 'forum2_user1', 'forum2_user2', 'forum2_user2', 'forum3_user1', 'forum3_user1', 'forum3_user2', 'forum3_user2'), to = c('forum1_user1', 'forum1_user2', 'forum1_user1', 'forum1_user2', 'forum2_user1', 'forum2_user2', 'forum2_user1', 'forum2_user2', 'forum3_user1', 'forum3_user2', 'forum3_user1', 'forum3_user2'), weight = 1:12, timestamp = 1:12, subforum = c('forum1', 'forum1', 'forum1', 'forum1', 'forum2', 'forum2', 'forum2', 'forum2', 'forum3', 'forum3', 'forum3', 'forum3')) 

I try this:

 # Sort for later use in scale_discrete df.edges <- df.edges %>% arrange(timestamp) gg <- ggplot(df.edges, aes(x = from, y = to, fill = weight)) + geom_raster() + coord_fixed() + facet_grid(. ~subforum, scales='fixed') + scale_x_discrete("from", aes(limits = from))+ scale_y_discrete("to", aes(limits = from)) + theme_bw() + theme(axis.line = element_blank(), axis.text.x = element_text(angle = 90, hjust=1, size=8), axis.text.y = element_text(hjust=1, size=10), axis.ticks = element_blank(), strip.background = element_rect(fill = 'white'), aspect.ratio = 1) + ggtitle("Matrix of interactions") + xlab('from') + ylab('to') print(gg) 

which gives the following:

enter image description here

And if I set the scale to the facet scale='free' :

enter image description here

However, I want each facet to show only users who belong to this forum. Matrices should be completely filled with 4 cells in each.

Any idea?

+2
source share
1 answer

You can create a separate schedule for each subforum level, and then lay them out together using grid.arrange :

 library(gridExtra) library(grid) 

First create separate graphs and save them in a list. Add scale_fill_continuous(limits=range(df.edges$weight)) to provide a consistent fill gradient on three graphs:

 pl = lapply(split(df.edges, df.edges$subforum), function(df) { ggplot(df, aes(x = from, y = to, fill = weight)) + geom_raster() + coord_fixed() + facet_grid(. ~subforum, scales='fixed') + scale_x_discrete("from", aes(limits = from))+ scale_y_discrete("to", aes(limits = from)) + scale_fill_continuous(limits=range(df.edges$weight)) + theme_bw() + theme(axis.line = element_blank(), axis.text.x = element_text(angle = 90, hjust=1, size=8), axis.text.y = element_text(hjust=1, size=10), axis.ticks = element_blank(), strip.background = element_rect(fill = 'white'), aspect.ratio = 1) + xlab('from') + ylab('to') }) 

Retrieve the legend as we want only one legend, not a separate legend for each plot:

 # Function to extract legend #https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs g_legend<-function(a.gplot){ tmp <- ggplot_gtable(ggplot_build(a.gplot)) leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box") legend <- tmp$grobs[[leg]] return(legend) } # Extract legend as a grob leg = g_legend(pl[[1]]) 

Sort stories with legend and title:

 grid.arrange( textGrob("Matrix of Interactions"), arrangeGrob( arrangeGrob(grobs=lapply(pl, function(x) x + guides(fill=FALSE)), ncol=3), leg, ncol=2, widths=c(10,1) ), heights=c(1,20) ) 

enter image description here

+3
source

Source: https://habr.com/ru/post/1257468/


All Articles