R语言 | 用image函数绘制热图heatmap

R语言中绘制热图heatmap的包(package)有很多,除了许多炫酷的第三方包外,系统自带的image函数使用起来也十分方便灵活。

1.主要绘制参数

image(x, y, z, zlim, xlim, ylim, col = heat.colors(12), 
      xlab, ylab, breaks, ...)  
z: 用于画图的数据,矩阵类型
x, y: 数据在x和y轴的坐标
zlim: 数据的范围,默认值是z矩阵中的最小值到最大值
xlim, ylim: 图片中x和y的数据阈值
col: 设定颜色阈值
breaks: 颜色对应的数据断点
xlab, ylab: x轴和y轴的标题

2.绘制常规heatmap

假设我们有RNA-Seq的两个重复(replicates),一共有20个基因

# 产生样本数据
m <- data.frame(
  rep1 = sample(1:20),
  rep2 = sample(1:20)
)

# 写一个绘图函数
draw_image <- function(data, axis = FALSE, label = FALSE) {
  # 设定绘图参数
  breaks.frequency <- seq(from=min(data), to=max(data), length.out=10)
  myColors <- colorRampPalette(c("white", "#2874A6"))

  # 产生图片
  image(1:nrow(data), 1:ncol(data), as.matrix(data),  breaks=breaks.frequency,      col=myColors(length(breaks.frequency)-1), axes = axis, cex = 1.5, xlab = "", ylab = "")

  # 自定义axis
  if (axis) {
    axis(2, 1:ncol(data), colnames(data), cex.axis=2.5)
    axis(1, 1:nrow(data), rownames(mxdata), cex.axis=2.5)
  }

# 自定义文本
  if (label) {
    for (x in 1:nrow(data)) {
      for (y in 1:ncol(data))  {
        text(x, y, data[x, y], cex = 2)
        }
    }
  }
}
# 绘制图形
draw_image(data, FALSE, FALSE)

3.数据分组后再产生heatmap

有时候数据里包含成百上千个基因,我们会想知道一些浓缩的结果,这时可以把表达量转换成离散型的数据,将表达量分成由高到低的不同组别,统计每个组别中的个数,这样可以更清晰的展示结果。

# 产生样本数据
myProbs <- seq(0, 0.95, 0.05) 
mx <- data.frame(
  sample1 = sample(1:20, 100, replace = T, prob = myProbs),
  sample2 = sample(1:20, 100, replace = T, prob = rev(myProbs))
)

# 创建分组函数
calc_type  <- function(x, column) {
  type <- apply(x, 1, function(y){no=as.numeric(y[column]);
  if(no >= 15){"15-20"}
  else if(no >= 10){"10-15"}
  else if(no >= 5){"5-10"}
  else{"0-5"}
  })
  type <- factor(type, levels = c("0-5", "5-10", "10-15", "15-20"))
} 

# 将每个基因在两个sample中的表达量划分到相应组别中
mx$type1 <- calc_type(mx, 1)
mx$type2 <- calc_type(mx, 2)

# 转换数据框为矩阵
# mx是行数和列数相等的矩阵
mx <- as.matrix(as.data.frame.matrix(table(mx$type1, mx$type2)))

# 查看数据,可以看到sample1处于高表达量的基因个数明显高于sample2
mx
# 0-5 5-10 10-15 15-20
# 0-5     1    2     0     0
# 5-10    4    3     6     1
# 10-15  10   11     6     1
# 15-20  17   15    13    10
                
# 绘制图,可以明显区分sample1和sample2的差别
draw_image(mx, TRUE, TRUE)

4. 添加scale

以下代码可以添加颜色的scale

# 创建颜色scale
# 以下代码来自https://www.r-bloggers.com/new-version-of-image-scale-function/
image.scale <- function(z, zlim, col = heat.colors(12),
                        breaks, horiz=TRUE, ylim=NULL, xlim=NULL, ...){
  if(!missing(breaks)){
    if(length(breaks) != (length(col)+1)){stop("must have one more break than colour")}
  }
  if(missing(breaks) & !missing(zlim)){
    breaks <- seq(zlim[1], zlim[2], length.out=(length(col)+1)) 
  }
  if(missing(breaks) & missing(zlim)){
    zlim <- range(z, na.rm=TRUE)
    zlim[2] <- zlim[2]+c(zlim[2]-zlim[1])*(1E-3)#adds a bit to the range in both directions
    zlim[1] <- zlim[1]-c(zlim[2]-zlim[1])*(1E-3)
    breaks <- seq(zlim[1], zlim[2], length.out=(length(col)+1))
  }
  poly <- vector(mode="list", length(col))
  for(i in seq(poly)){
    poly[[i]] <- c(breaks[i], breaks[i+1], breaks[i+1], breaks[i])
  }
  xaxt <- ifelse(horiz, "s", "n")
  yaxt <- ifelse(horiz, "n", "s")
  if(horiz){YLIM<-c(0,1); XLIM<-range(breaks)}
  if(!horiz){YLIM<-range(breaks); XLIM<-c(0,1)}
  if(missing(xlim)) xlim=XLIM
  if(missing(ylim)) ylim=YLIM
  plot(1,1,t="n",ylim=ylim, xlim=xlim, xaxt=xaxt, yaxt=yaxt, xaxs="i", yaxs="i", ...)  
  for(i in seq(poly)){
    if(horiz){
      olygon(poly[[i]], c(0,0,1,1), col=col[i], border=NA)
    }
    if(!horiz){
      polygon(c(0,0,1,1), poly[[i]], col=col[i], border=NA)
    }
  }
}

# 绘制颜色scale
breaks.frequency <- seq(from=min(mx), to=max(mx), length.out=10)
myColors <- colorRampPalette(c("white", "#2874A6"))
image.scale(mx, mx, myColors(length(breaks.frequency)-1), breaks.frequency)

参考资料
image.scale地址:https://www.r-bloggers.com/new-version-of-image-scale-function/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343