Reputation: 71
I am trying to assign different colour scales to my dataset based on the column variable. The dummy code is
df1 <- data.frame(ID = c('a1', 'b1', 'c1', 'd1', 'e1', 'f1'),
var1 = c('a', 'b', 'c', 'a', 'b', 'c'),
var2 = c(0.006, 0.04, .005, 0, 0.02, 0.05))
Instead of an overall colour scale, I want 'a' from var1 to be red to white, 'b'blue to white, and 'c' as purple to white. I have 4000 rows in my actual data, I tried to nest each on top of each other, but failed.. the running is below. Please suggest where do I need to make the changes to get my desired output.
P.S.I know, the var2 will have different high's and lows, if legend is available, great, otherwise I just need to show color differences.
ggplot(df1,aes(y = var1, x = ID, fill = var2)) +
geom_tile(color = "white") +
coord_equal() +
scale_fill_gradient(low = "steelblue", high = "white") +
ylab("var1") +
xlab("ID") +
theme(legend.title = element_text(size = 10),
legend.text = element_text(size = 12),
plot.title = element_text(size = 16),
axis.title = element_text(size = 14, face = "bold"),
axis.text.x = element_text(angle = 90, hjust = 1)) +
labs(fill = "ABC association")
Upvotes: 2
Views: 1262
Reputation: 29085
If you want each colour scale to take on a gradient between a specific colour and white, you can fake it by assigning a different colour to each var1
value, and vary the transparency based on var2. Here's an illustration, though of course you can vary the details depending on how you want the results to appear:
Step 1. Define the colour for each var1 value.
color.scale <- c("a" = "red", "b" = "blue", "c" = "purple")
Step 2. Scale the range of var2
values within each var1
category to a common range.
library(dplyr)
df2 <- df1 %>%
group_by(var1) %>%
mutate(var2.alpha = scale(var2)) %>%
ungroup() %>%
arrange(var1)
> df2
# A tibble: 6 x 4
ID var1 var2 var2.alpha
<fctr> <fctr> <dbl> <dbl>
1 a1 a 0.00600 0.707
2 d1 a 0 -0.707
3 b1 b 0.0400 0.707
4 e1 b 0.0200 -0.707
5 c1 c 0.00500 -0.707
6 f1 c 0.0500 0.707
Step 3. Create your plot. The first white geom_tile()
provides a "backing" for the coloured tile layer, so that background elements (panel colour, grid lines, etc) don't show up within the tiles.
p.plot <- ggplot(df2,
aes(x = ID, y = var1, fill = var1, alpha = var2.alpha)) +
geom_tile(fill = "white", alpha = 1) +
geom_tile() +
scale_fill_manual(values = color.scale) +
scale_alpha(range = c(0.1, 0.9)) +
coord_equal() +
theme_light() +
theme(legend.position = "none")
Step 4. Create a separate plot to serve as the legend.
df3 <- df2 %>% group_by(var1) %>%
summarise(min = min(var2), max = max(var2)) %>%
mutate(tile.1 = 0.1, tile.3 = 0.3, tile.5 = 0.5, tile.7 = 0.7, tile.9 = 0.9) %>%
tidyr::gather(tile, value, -var1, -min, -max)
p.legend <- ggplot(df3, aes(x = value, y = var1, fill = var1, alpha = value)) +
geom_tile() +
geom_text(aes(label = var1), x = -0.1) +
geom_text(aes(label = min), x = 0.1) +
geom_text(aes(label = max), x = 0.9, color = "white") +
ggtitle("ABC association") +
coord_cartesian(xlim = c(-0.2, 1.1)) +
scale_fill_manual(values = color.scale) +
scale_alpha_identity() +
theme_void() +
theme(legend.position = "none")
Step 5. Combine the two, allocating more space to the main plot.
cowplot::plot_grid(p.plot, p.legend,
ncol = 1, align = "v",
rel_heights = c(5, 1))
Upvotes: 4