简体   繁体   English

根据类别绘制手动图例ggplot2

[英]Plotting manual legend ggplot2 based on categories

I'm building a visualisation of a dataset using the geom_tile function in ggplot2. 我正在使用ggplot2中的geom_tile函数构建数据集的可视化。 I'm almost satisfied with it, however I'd like to add a particular legend to it, but I haven't been able to find a suitable method for this. 我对它几乎感到满意,但是我想添加一个特定的图例,但我还没有找到合适的方法。 I'll explain what I mean exactly later on in the post. 我将在后期解释我的意思。

Here's the code that I'm currently using, it's probably a huge mess as I'm not proficient in R and basically generated this by trial and error. 这是我目前正在使用的代码,它可能是一个巨大的混乱因为我不精通R并且基本上是通过反复试验产生的。 If anyone is willing to clean it up, knock yourself out :-) . 如果有人愿意清理它,请把自己打倒:-)。

#Read source data
meta <- read.csv("Dropbox/meta_censored.csv")

#import libraries  
library("ggplot2")
library("plyr")
library("reshape2")
library("scales")
library("grid")

#transform and rescale data in prep for later steps
meta.m <- melt(meta)
meta.s <- ddply(meta.m, .(variable), transform,
                rescale = scale(value))


#generate categories to sort conditions by colour
meta.s$Category <- meta.s$variable
levels(meta.s$Category) <-
  list("1_early" = c("X1", "X2"),
       "2_early" = c("X3", "X4", "X5", "X6", "X7"),
       "1_late" = c("X10", "X17"),
       "2_late" = c("X8", "X9", "X11", "X12", "X14", "X15", "X16"),
       "3_late" = "X13",
       "4_late" = c("X18", "X19"))

#define colours per category
meta.s$rescaleoffset <- meta.s$rescale + 100*(as.numeric(meta.s$Category)-1)
scalerange <- range(meta.s$rescale)
gradientends <- scalerange + rep(c(0,100,200,300,400,500), each = 2)
colorends <- c("white", "red", "white", "green", "white", "red", "white", "green", "white", "orange", "white", "purple")

#reorder by category
meta.s$variable2 <- reorder(meta.s$variable, as.numeric(meta.s$Category))

#reverse y axis labels (were z-a, now a-z)
flevels <- levels(meta.s$Param)
flevels <- rev(flevels)

#x axis annotation variables
text_early <- textGrob("Early", gp=gpar(fontsize = 5, fontface = "bold", col = "red"))
text_late <- textGrob("Late", gp=gpar(fontsize = 5, fontface = "bold", col = "red"))

#plot heatmap
p <- ggplot(meta.s, aes(variable2, Param)) +
  geom_tile(aes(fill = rescaleoffset), colour = "lightgrey") + 
  #add line to seperate early from late
  geom_vline(xintercept = 7.5) +
  scale_fill_gradientn(colours = colorends, values = rescale(gradientends)) +
  scale_x_discrete("", expand = c(0, 0)) +
  scale_y_discrete("", limits = flevels, expand = c(0, 0)) +
  theme_grey(base_size = 5) + 
  theme(legend.position = "right",
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 270, hjust = 0, size = 5, vjust = 0, face = "bold"),
        plot.margin = unit(c(1,1,2,1), "lines")) +
  annotation_custom(text_early, xmin = 0, xmax = 8, ymin=168.5, ymax = 168.5) +
  annotation_custom(text_late, xmin = 8, xmax = 19, ymin=168.5, ymax = 168.5)

gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)

Basically, I'm trying to show values per object in column Param by each value on the x axis. 基本上,我试图通过x轴上的每个值在列Param中显示每个对象的值。 Each value on the x axis represents a different study, with different experimental conditions. x轴上的每个值代表不同的研究,具有不同的实验条件。 I have tried grouping them using this thread , and each group gets a different colour. 我尝试使用此线程对它们进行分组,并且每个组都获得不同的颜色。

Now what I ideally want is that the legend displays the respective solid colour for each category, and not an overall gradient based on the value of each of the cells. 现在我理想的是,图例显示每个类别的相应纯色,而不是基于每个单元格的值的整体渐变。 Of course it doesn't need to be a legend produced with ggplot2, any other method is accepted as long as it does the trick. 当然,它不需要是使用ggplot2生成的图例,只要有技巧,任何其他方法都可以接受。

Thanks in advance! 提前致谢!

You can include shape = Category (which won't change the appearance of the plot as it has no effect in geom_tile ) and then use override.aes to get the colours for each Category. 你可以包括shape = Category (它不会改变绘图的外观,因为它在geom_tile没有效果),然后使用override.aes来获取每个Category的颜色。 If you only want 4 categories you can use substr to define the fill colour based on the number (1st element). 如果您只需要4个类别,则可以使用substr根据数字定义填充颜色(第1个元素)。 In order to remove the gradient legend you can add guide = FALSE to scale_fill_gradientn : 要删除渐变图例,可以将guide = FALSE添加到scale_fill_gradientn

ggplot(meta.s, aes(variable2, Param)) +
  geom_tile(aes(fill = rescaleoffset, shape = substr(Category, 1, 1)), colour = "lightgrey", show.legend = TRUE) + 
  #add line to seperate early from late
  geom_vline(xintercept = 7.5) +
  scale_fill_gradientn(colours = colorends, values = rescale(gradientends), guide = FALSE) +
  scale_x_discrete("", expand = c(0, 0)) +
  scale_y_discrete("", limits = flevels, expand = c(0, 0)) +
  theme_grey(base_size = 5) + 
  theme(legend.position = "right",
        axis.ticks = element_blank(),
        axis.text.x = element_text(angle = 270, hjust = 0, size = 5, vjust = 0, face = "bold"),
        plot.margin = unit(c(1,1,2,1), "lines")) +
  annotation_custom(text_early, xmin = 0, xmax = 8, ymin=168.5, ymax = 168.5) +
  annotation_custom(text_late, xmin = 8, xmax = 19, ymin=168.5, ymax = 168.5) +
  guides(shape = guide_legend("Category", override.aes = list(fill = c("red", "green", "orange", "purple"))))

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM