Home > database >  Add noise to ggplot heatmap where the amount of noise is based on a value?
Add noise to ggplot heatmap where the amount of noise is based on a value?

Time:05-09

I am trying to add noise or dithering to a ggplot heatmap, where the amount of noise in each tile is determined by a value.

for example, If I make a heatmap like so:

library(tidyr)
library(tibble)
library(ggplot2)

set.seed(100)
s<-matrix(runif(25,0,1),5)
s[lower.tri(s)] = t(s)[lower.tri(s)]
diag(s) <- 0
colnames(s) <- rownames(s) <- paste0('x', 1:5)

df <- reshape2::melt(s) 

ggplot(df, aes(x = Var1, y = Var2, fill = value))  
  geom_tile()  
  scale_fill_viridis_c()  
  theme_bw()  
  theme(aspect.ratio = 1)

This results in something like: example heatmap

However, I would like to add noise to each tile of the heatmap based on a certain value. For example, if I add another column to my data frame to represent the noise:

df$noise <- runif(25)

I am trying to make something like: heatmap with noise

I made the above plot in photoshop. But I was wondering if it is possible to make something like this in ggplot? So, for example, if one tile had a noise value of 0, then there would be no noise/dithering on that tile... and if the tile had a noise/dithering value of 1, there would be a lot of noise on that tile.

CodePudding user response:

Here's an approach using tidyr::uncount to make copies of each cell, and then assigning a degree of noise based on the noise variable.

library(tidyverse)
df %>%
  uncount(25, .id = "id") %>%
  mutate(value2 = value   rnorm(n(), sd = noise),
         Var1_offset = (id - 1) %% 5,
         Var2_offset = (id - 1) %/% 5) %>%
  ggplot(aes(as.numeric(Var1)   Var1_offset/5, 
             as.numeric(Var2)   Var2_offset/5, 
             fill = value2))  
    geom_tile()  
    scale_fill_viridis_c()  
    theme_bw()  
    theme(aspect.ratio = 1)  
  scale_x_continuous(breaks = 0.5   (1:5),
                     labels = paste0("x", 1:5), name = "Var1")  
  scale_y_continuous(breaks = 0.5   (1:5),
                     labels = paste0("x", 1:5), name = "Var2")

enter image description here

  • Related