ShellfishGene
ShellfishGene

Reputation: 345

Extend data frame for plotting heat map in ggplot2

I want to generate a heat map from an all-vs-all comparison. I have the data, already scaled to 0-1. However, I have the values only for the comparisons in one way, and not for the comparisons between the same group (which are always 1), i.e. I have half the matrix and am missing the other half and the diagonal. What is a good way to get it into a form that ggplot2 can use for the heat map?

This is an example of the data I have:

A    B    value   
T1    T2    0.347
T1    T3    0.669
T2    T3    0.214

I assume the following is what I need for ggplot (or maybe I don't, if ggplot can somehow generate it?):

A    B    value   
T1    T2    0.347
T1    T3    0.669
T2    T3    0.214
T2    T1    0.347
T3    T1    0.669
T3    T2    0.214
T1    T1    1
T2    T2    1
T3    T3    1

Then I would run

sorted<-data[order(data$A, data$B), ]

ggplot(sorted, aes(A, B)) +
  geom_tile(aes(fill = value), colour = "white") +
  scale_fill_gradient(low = "black", high = "red") +

I have solved this, but in (what I assume is) a really bad way involving for loops. There must be a better way to get form the first data frame above to the second!

Cheers

Upvotes: 2

Views: 825

Answers (1)

Matt Parker
Matt Parker

Reputation: 27359

Hmm... I can imagine an elegant built-in existing, but this should do the trick for you:

# Factors are not your friend here
options(stringsAsFactors = FALSE)

# Here's the data you're starting with
this.half <- data.frame(A = c("T1", "T1", "T2"),
                        B = c("T2", "T3", "T3"),
                        value = c(0.347, 0.669, 0.214))


# Make a new data.frame, simply reversing A and B
that.half <- data.frame(A = this.half$B,
                        B = this.half$A,
                        value = this.half$value)

# Here's the diagonal
diagonal <- data.frame(A = unique(c(this.half$A, this.half$B)),
                       B = unique(c(this.half$A, this.half$B)),
                       value = 1)

# Mash 'em all together
full <- rbind(this.half, that.half, diagonal)

Upvotes: 1

Related Questions