Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use facet_grid for pairwise value (heatmap) visualization in ggplot2

I have data containing pairwise numerical data for 10 samples:

data = dget(url("https://git.io/vCTpG"))

The data looks like this:

sampleB  sampleA  ol   labelA  labelB  facetA  facetB
2409     2409     100  2409|B  2409|B  B       B
2409     2413     0    2413|A  2409|B  A       B
2409     2414     0    2414|A  2409|B  A       B
2409     2417     0    2417|C  2409|B  C       B
2409     2411     0    2411|A  2409|B  A       B
2409     2418     0    2418|B  2409|B  B       B
2409     2416     0    2416|C  2409|B  C       B
2409     2412     4    2412|B  2409|B  B       B
2409     2415     0    2415|C  2409|B  C       B
2409     2410     19   2410|A  2409|B  A       B
...      ...      ...  ...     ...     ...     ...

I want to visualize the ol values in a heat map:

library(ggplot2)
ggplot(data = data, mapping = aes(x=labelA, y=labelB)) + 
  geom_tile(mapping = aes(fill=ol)) +
  scale_fill_gradient(low = "white", high = "black") + 
  theme(legend.position = "none") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

plot without facet

Now I'd like to structure the 10 by 10 heat map by a category each sample is associated with, namely A,B or C in this example. However, if I use facet_grid ...

last_plot() + facet_grid(facetA~facetB)

plot with facet

... this results in a 30 by 30 rather than in a 10 by 10 heat map which is subdivided into 3 categories (still showing only 100 values though). I remember having fixed this using

last_plot() + facet_grid(facetA~facetB, scales = "free", space = "free")

in the past, however, I can't reproduce this anymore. The desired solution would look like this (this was gimped, not ggplot generated):

enter image description here

I.e. a reordered, grouped 10 by 10 matrix.

like image 620
barbaz Avatar asked Oct 30 '22 17:10

barbaz


1 Answers

You need to use facet_wrap() instead of facet_grid() or change the order of the facets in facet_grid() as suggested in the comments.

The reason is that, by definition, facet_grid does not allow y-axes limits to be different across panels in the same row. In other words, all three panels in the top row must have the same y limits, all three panels in the second row must have the same y limits, etc. Adding scales = "free_y" means that the first row is allowed to have different y limits from the second row (but within a given row, all panels must always have the same y limits). In your example, when you use

facet_grid(facetA ~ facetB, scales = "free")

you are forcing ggplot to use all of the y values for all rows; eg the left panel in the top row must contain the value 2418|B because that value is present in the middle panel of the top row. Reversing the order of facets happens to do the job in this case because of the structure of your data. (I'm just giving an example for the y axis, but the same holds for the x axis limits when using scales = "free_x".)

If you want to have different x and y scales for each and every panel, independently of the ones next to it, you will need to use facet_wrap.

Edit A more detailed explanation of how to get the figure you want. Going back to your specific example, reversing your facets will give

p <- ggplot(data = data, mapping = aes(x=labelA, y=labelB)) + 
    geom_tile(mapping = aes(fill=ol)) +
    scale_fill_gradient(low = "white", high = "black") + 
    theme(legend.position = "none") +
    theme(axis.text.x = element_text(angle = 90, hjust = 1)) + 
    facet_grid(facetB ~ facetA, scales = "free")
p

enter image description here

This contains all the panels you want. To get the order you are asking for is simply a matter of rearranging the rows. This can be done by setting the order of the levels of facetB (edit: or, as @user20650 suggested in the comments, by setting as.table=FALSE in facet_grid()):

data1 <- data    
data1$facetB <- factor(data1$facetB, levels = c("C", "B", "A"))
p %+% data1

enter image description here

like image 80
konvas Avatar answered Nov 12 '22 20:11

konvas