在具有不同x-y轴的面中绘制多个矩阵

时间:2016-07-23 20:06:15

标签: r ggplot2 geom-raster

我从一组在线论坛中收集了数据,并希望使用ggplot和facets(每个论坛一个方面)进行绘图,该矩阵表示用户A回复用户B的次数。

以下是加载玩具示例的代码:

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

我试试这个:

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

给出了这个:

enter image description here

如果我设置方面比例scale='free'

enter image description here

但是,我希望每个方面只显示属于该论坛的用户。矩阵应该完全填充每个矩阵中的4个单元格。

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

您可以为subforum的每个级别创建单独的绘图,然后使用grid.arrange将它们放在一起:

library(gridExtra)
library(grid)

首先,创建单独的图并存储在列表中。我们添加scale_fill_continuous(limits=range(df.edges$weight))以确保三个图中的填充渐变一致:

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') 
  })

提取图例,因为我们只需要一个图例,而不是每个图的单独图例:

# 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]])

使用图例和标题排列图:

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