ggplot2的梯度密度填充?

时间:2017-09-11 21:04:34

标签: r ggplot2

我已经生成了一个ggplot2图表,我想填写它显示点的密度。我使用以下密度公式管理它:

get_density <- function(x, y, n = 250) {
  dens <- MASS::kde2d(x = x, y = y, n = n)
  ix <- findInterval(x, dens$x)
  iy <- findInterval(y, dens$y)
  ii <- cbind(ix, iy)
  return(dens$z[ii])}

然后在新的密度中获得点的密度&#34;基于公式的列,用&#34; lfc&#34;和&#34; pval&#34;是x,y变量:

data.MA$density <- get_density(data.MA$pval, data.MA$lfc)

我正在绘制的ggplot对象是:

  heatmap2 <- ggplot() + 
  geom_point(data = filter(data.MA, chg == "unchanged"), 
             aes(basemean, lfc, color = density)) + 
  geom_point(data = filter(data.MA, chg == "changed"), 
             aes(basemean, lfc, fill = dir), 
             shape = 21, size = 2, stroke = 0.1) +
  scale_fill_manual(values = c("#FFA600", "#00B2FF", "#00B2FF")) +
  scale_colour_gradient2(low = "blue", mid = "white", high = "red", midpoint = 10) +
  theme_bw() + scale_y_continuous() + scale_x_continuous()

这给了我以下图表:

MA plot gradient

以下是数据样本.MA:

gene     pval  lfc basemean      density       dir peakid     chg
1    NXT1 41.22403 3.58     9.50 3.339690e-02 increased      1 changed
2   BEND5 23.41567 5.03     8.01 0.000000e+00 increased      2 changed
3    PLB1 23.19450 7.91     8.13 4.849746e-78 increased      3 changed
4   LYRM9 20.81531 2.35    11.43 0.000000e+00 increased      4 changed
5 MIR4464 14.73049 3.65     7.99 0.000000e+00 increased      5 changed
6 HSD17B2 14.63451 4.51     7.31 0.000000e+00 increased      6 changed

我的问题是如何让渐变在中间更加分散,所以它不仅仅是中间的红色条纹而是更多的渐变?

任何人都可以建议一个不同的密度公式吗?

或者更好地定义渐变的方法是在更单独的块中?

1 个答案:

答案 0 :(得分:1)

数据样本太小,无法尝试重现绘图并检查可能的解决方案,但这是尝试使用scale_colour_gradientn并强调中点

#emulating your solution:

df = data.frame(seq = 1:1000, rnorm= rnorm(1000)+5)

library(ggplot2)
A = ggplot(df) + 
      geom_point(aes(seq, rnorm, color = rnorm)) + 
      scale_colour_gradient2(low = "blue", mid = "white", high = "red", midpoint = 5) +
      theme_bw() + scale_y_continuous() + scale_x_continuous()

#providing a function for making gradients
colfunc = colorRampPalette(c("blue", "white", "red"))
#providing an exponential gradient
exp_seq= seq(from = 0.1, to = 0.6, length.out = 4)^2
B = ggplot(df) + 
      geom_point(aes(seq, rnorm, color = rnorm)) + 
      scale_colour_gradientn(colors=colfunc(11), values = c(0, exp_seq, rev(1-exp_seq), 1)) +
      theme_bw() + scale_y_continuous() + scale_x_continuous() 

library(cowplot)
plot_grid(A, B, ncol = 2)

enter image description here

编辑

values函数的参数scale_colour_gradientn接受一个值为0到1的向量。此向量中的元素应该与颜色一样多。

colfunc(11)是一个生成颜色矢量的函数,在这种情况下,它将输出11种颜色,因为参数被指定为11.因此values的参数scale_colour_gradientn需要有11个值,它将映射颜色。这些值与函数scales::rescale的数据相关 (https://www.rdocumentation.org/packages/scales/versions/0.4.1/topics/rescale) 它获取您的数据范围并将其映射到0 - 1范围。如果您的数据范围例如是100 - 400,并且您希望中点位于153,那么:

scales::rescale(c(100, 153, 400)) 
#output 0.0000000 0.1766667 1.0000000

你想要映射&#34; white&#34; color(在上例中为colors参数指定的向量的元素6)颜色为0.1766667,除此之外,您需要指定0 - 0.1766667范围内的其他4个元素用于浅蓝色,另外4个元素用于浅红色。例如,

values = c(0, 0.01, 0.03, 0.6, 0.1, 0.1766667, 0.3, 0.5, 0.7, 0.9, 1) 但这有点武断,也许更好的策略是检查你的数据,看看你想强调的范围,并选择这些值。例如:

数据范围为100到400,您希望中​​点为153并强调123 - 183,您可以为值参数提供自定义范围:

scales::rescale(c(100, 113, 123, 133, 143, 153, 163, 173, 183, 193, 400))
#output 0.00000000 0.04333333 0.07666667 0.11000000 0.14333333 0.17666667 0.21000000 0.24333333 0.27666667 0.31000000 1.00000000

在exp_seq部分我就是 定义了一个向量exp_seq= seq(from = 0.1, to = 0.6, length.out = 4)^2

exp_seq
#output 0.01000000 0.07111111 0.18777778 0.36000000

rev(exp_seq) #just the reverse
#output 0.36000000 0.18777778 0.07111111 0.01000000

并将其包含在另一个载体中

c(0, exp_seq, 1-rev(exp_seq), 1)
#output 0.00000000 0.01000000 0.07111111 0.18777778 0.36000000 0.64000000 0.81222222 0.92888889 0.99000000 1.00000000

并将其传递给values参数以映射我在colors参数中定义的11种颜色。 如果我这样做:

ggplot(df) + 
  geom_point(aes(seq, rnorm, color = rnorm)) + 
  scale_colour_gradientn(colors=colfunc(11), values = scales::rescale(c(100, 113, 123, 133, 143, 153, 163, 173, 183, 193, 400))) +
  theme_bw() + scale_y_continuous() + scale_x_continuous() 

结果如下:

enter image description here

如果有任何不清楚的地方,请告诉我。