2

How can I put two columns in one heatmap? Lets say I have the following data

data<- structure(list(names = structure(c(5L, 1L, 10L, 2L, 6L, 4L, 9L, 
7L, 11L, 3L, 8L), .Label = c("Bin", "Dari", "Down", "How", "India", 
"Karachi", "Left", "middle", "Right", "Trash", "Up"), class = "factor"), 
    X1Huor = c(1.555555556, 5.2555556, 2.256544, 2.3654225, 1.2665545, 
    0, 1.889822365, 2.37232101, -1, -1.885618083, 1.128576187
    ), X2Hour = c(1.36558854, 2.254887, 2.3333333, 0.22255444, 
    2.256588, 5.66666, -0.377964473, 0.107211253, -1, 0, 0), 
    X3Hour = c(0, 1.222222222, 5.336666, 1.179323788, 0.832050294, 
    -0.397359707, 0.185695338, 1.393746295, -1, -2.121320344, 
    1.523019248), X4Hour = c(3.988620176, 3.544745039, -2.365555, 
    2.366666, 1.000000225, -0.662266179, -0.557086015, 0.862662186, 
    0, -1.305459824, 1.929157714), X5Hour = c(2.366666, 2.333365, 
    4.22222, 0.823333333, 0.980196059, -2.516611478, 2.267786838, 
    0.32163376, 0, -2.592724864, 0.816496581)), .Names = c("names", 
"X1Huor", "X2Hour", "X3Hour", "X4Hour", "X5Hour"), class = "data.frame", row.names = c(NA, 
-11L))

This data has 5 columns of values. I want to make a heatmap which half of it is the value from first colum and the other half of each cell is from the second column.

The same for the third column and fourth

The same for the fifth and sixth ( there is no sixth but I can leave it empty)

This is just an example to show what I am looking for. I have searched a lot but I could not find anything like this

enter image description here

The color range from Red to green, if the value is higher than 2 the color red and if the value is lower than -2 the color is green.

Any thought how to do this ?

nik
  • 2,500
  • 5
  • 21
  • 48
  • You can probably achieve this using geom_polygon. These are essentially polygons, so to create them you would need to reshape your data and add the polygon positions manually. – yeedle Mar 22 '17 at 02:45
  • @yeedle if you can please give a solution, I will accept it – nik Mar 22 '17 at 02:57
  • I don't have a programmatic solution, but I can show you how to get started – yeedle Mar 22 '17 at 02:58
  • @yeedle that is going to be so difficult I guess, have a look at this http://stackoverflow.com/questions/25449093/ggplot2-geom-polygon-with-no-fill – nik Mar 22 '17 at 03:01
  • Not really. It will just be a matter of duplicating your data in the correct order. I actually think I have an idea of how to do it – yeedle Mar 22 '17 at 03:04

1 Answers1

2

This is a somewhat hacky solution, but it might work for you, so check this out.

The idea is to utilize geom_polygon to create the triangles and stack them. To do that we first need to generate the triangle coordinates

library(dplyr)
library(tidyr)
library(stringr)

# the following two line create the triangle coordinates
x = rep(c(1,2,2, 1, 1, 2),nrow(data))
y = rep(c(1,1,2, 1, 2, 2),nrow(data)) + rep(0:10, each=6)

Now that we have our coordinates we need to generate their ids, which are the names. But because we want each triangle to be unique, we need to create two unique versions of each name:

names <- data %>% 
  select(names, X1Huor, X2Hour) %>% 
  gather("key", "value", X1Huor, X2Hour) %>%
  arrange(names, key) %>% 
  mutate(name = str_c(names, key)) %>%
  .$name %>% 
  rep(each = 3)

And now we do the same with the hours:

hour <- data %>% 
  select(names, X1Huor, X2Hour) %>% 
  gather("key", "value", X1Huor, X2Hour) %>%
  arrange(names, key) %>% 
  .$value %>% 
  rep(each = 3)

datapoly <- data.frame(x = x, y = y , hour = hour, names = names)

Since there are no proper labels for the plot in our datapoly df, we need to create one:

name_labels <- data %>% 
  select(names) %>% 
  arrange(names) %>%
  .$names

The scene is now set for our graph:

ggplot(datapoly, aes(x = x, y = y)) +
  geom_polygon(aes(group = names, fill = hour), color = "black") +
  scale_fill_continuous(low = "green", high = "red") +
  scale_y_continuous(breaks = 1:nrow(data), labels = name_labels) +
  theme(axis.text.y = element_text(vjust = -2),
        axis.ticks = element_blank(),
        axis.text.x = element_blank(),
        axis.title = element_blank())

The output looks like this:

plot

Several points to keep in mind: Is this really a plot you want to be creating and using? Is this really useful for your purposes? Perhaps other, more traditional visualization methods are more suitable. Also, I didn't bother doing the same for the other hour columns as these are quite tedious, but the method on how to achieve them should be clear enough (I hope).

yeedle
  • 4,918
  • 1
  • 22
  • 22
  • thanks I am still waiting if someone else put some input, if no, I accept your answer – nik Mar 24 '17 at 22:54