R ggplot2:在热图的两侧添加自定义文本到图例和值计数

时间:2016-11-30 22:37:50

标签: ggplot2 heatmap

我的输入数据如下:

COMPANY      DOMAIN    REVIEW    PROGRESS
Company A    Service   Good      +
Company A    Response  Good      +
Company A    Delay     Very Good    
Company A    Cost      Poor      -
Company B    Service   Poor      -
Company B    Delay     Average  
Company B    Cost      Good      +
Company C    Service   Very Poor +
Company C    Cost      Average  

我制作了一张热图,其中我添加了一些文字(" PROGRESS"变量的值 - 即加号或减号)。heatmap produced

这是我的代码:

require("ggplot2")

graph <- read.table("input.tab", header=T, sep="\t")

ggplot(data=graph, aes(x=COMPANY, y=DOMAIN, group=REVIEW, fill=REVIEW)) + 

geom_tile() + 

geom_text(aes(x=COMPANY, y=DOMAIN, label=PROGRESS)) + 

scale_x_discrete(expand = c(0, 0)) + 

scale_y_discrete(expand = c(0, 0)) +

geom_vline(xintercept=seq(1.5, length(graph$COMPANY)+0.5)) + 
geom_hline(yintercept=seq(1.5, length(graph$DOMAIN)+0.5)) + 

theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    axis.line = element_blank(),
    axis.ticks = element_blank(),
    panel.background = element_blank(),
    plot.background = element_blank(),
    axis.title=element_blank(),
    axis.text.x = element_text(angle=45, size=12, hjust=1)
    )

然而,我正在努力添加(见下图手动修改):

(1)以下&#34;进展&#34;作为已列出的颜色代码的一部分的图例:

+   Better
-   Worse

(2)绘图右侧和图例

之间每行可用的数据计数

(3)在图表顶部的每列上可用的数据计数

enter image description here

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

这是我提出的解决方案,我在代码中添加了注释,让您了解我的所作所为。但是,可能有更好的方法来生成网格。希望它有所帮助。

graph <- read_csv(
"COMPANY      ,DOMAIN    ,REVIEW    ,PROGRESS
Company A    ,Service   ,Good      ,+
Company A    ,Response  ,Good      ,+
Company A    ,Delay     ,Very Good ,   
Company A    ,Cost      ,Poor      ,-
Company B    ,Service   ,Poor      ,-
Company B    ,Delay     ,Average  ,
Company B    ,Cost      ,Good      ,+
Company C    ,Service   ,Very Poor ,+
Company C    ,Cost      ,Average  ,")


ggplot() + 
  # moved aesthetics and data to each geom, 
  # if you keep them in the ggplot call,
  # you have to specify `inherit.aes = FALSE` in the rest of the geoms     
  geom_tile(data = graph,
            aes(x    = COMPANY, 
                y    = DOMAIN, 
                fill = REVIEW)) + 
  # changed from `geom_text` to `geom_point` with custom shapes
  geom_point(data = graph,
             aes(x     = COMPANY, 
                 y     = DOMAIN, 
                 shape = factor(PROGRESS, labels = c("Worse", "Better"))),
             size = 3) +
  # custom shape scale
  scale_shape_manual(name = "", values = c("-", "+")) +
  # calculate marginal totals "on the fly"
  # top total
  geom_text(data  = summarize(group_by(graph, COMPANY),
                              av_data  = length(!is.na(PROGRESS))),
            aes(x = COMPANY,
                y = length(unique(graph$DOMAIN)) + 0.7,
                label = av_data)) + 
  # right total
  geom_text(data  = summarize(group_by(graph, DOMAIN),
                              av_data  = length(!is.na(PROGRESS))),  
            aes(x = length(unique(graph$COMPANY)) + 0.7, 
                y = DOMAIN, label = av_data)) + 
  # expand the plotting area to accomodate for the marginal totals
  scale_x_discrete(expand = c(0, 0.8)) + 
  scale_y_discrete(expand = c(0, 0.8)) +
  # changed to `geom_segment` to generate the grid, otherwise grid extends
  # beyond the heatmap 
  # horizontal lines
  geom_segment(aes(y    = rep(0.5, 1 + length(unique(graph$COMPANY))),
                   yend = rep(length(unique(graph$DOMAIN)) + 0.5,
                              1 + length(unique(graph$COMPANY))),
                   x    = seq(0.5, 1 + length(unique(graph$COMPANY))),
                   xend = seq(0.5, 1 + length(unique(graph$COMPANY))))) + 
  # vertical lines
  geom_segment(aes(x    = rep(0.5, 1 + length(unique(graph$DOMAIN))),
                   xend = rep(length(unique(graph$COMPANY)) + 0.5, 
                              1 + length(unique(graph$DOMAIN))),
                   y    = seq(0.5, 1 + length(unique(graph$DOMAIN))),
                   yend = seq(0.5, 1 + length(unique(graph$DOMAIN))))) + 

  # custom legend order
  guides(fill  = guide_legend(order = 1), 
         shape = guide_legend(order = 2)) +
  # theme tweaks
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    axis.line        = element_blank(),
    axis.ticks       = element_blank(),
    panel.background = element_blank(),
    plot.background  = element_blank(),
    axis.title       = element_blank(),
    axis.text.x = element_text(angle = 45,
                               size  = 12,
                               hjust =  1,
                               # move text up 20 pt
                               margin = margin(-20,0,0,0, "pt")),
    # move text right 20 pt
    axis.text.y = element_text(margin = margin(0,-20,0,0, "pt"))
  )

final_plot