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))
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)
... 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):
I.e. a reordered, grouped 10 by 10 matrix.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With