I am trying to replicate this kind of plot using ggplot.
To achieve that, I need to have only the diagonal tiles as triangles. I have a single data frame with two batches of data.
df$Triangle == "Individual" (top triangle)
df$Triangle == "Population" (bottom triangle)
Here is my current code:
# Defines colour palette and breaks ~
color_palette <- c("#001260", "#EAEDE9", "#601200")
nHalf <- 4
Min <- -.1
Max <- .1
Thresh <- 0
rc1 <- colorRampPalette(colors = color_palette[1:2], space = "Lab")(nHalf)
rc2 <- colorRampPalette(colors = color_palette[2:3], space = "Lab")(nHalf)
rampcols <- c(rc1, rc2)
rampcols[c(nHalf, nHalf+1)] <- rgb(t(col2rgb(color_palette[2])), maxColorValue = 256)
rb1 <- seq(Min, Thresh, length.out = nHalf + 1)
rb2 <- seq(Thresh, Max, length.out = nHalf + 1)[-1]
rampbreaks <- c(rb1, rb2)
# Creates Ind_PLot ~
Ind_Plot <-
ggplot() +
geom_tile(data = subset(fulldf, Triangle == "Individual"), aes(Ind_1, Ind_2, fill = as.numeric(Value)), colour = "#000000") +
scale_x_discrete(expand = c(0, 0)) +
scale_y_discrete(expand = c(0, 0)) +
scale_fill_gradientn(colors = rampcols, breaks = rampbreaks, limits = c(-.1, .1)) +
facet_grid(K ~ CHRType, scales = "free", space = "free") +
theme(panel.background = element_rect(fill = "#ffffff"),
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.spacing = unit(1, "lines"),
legend.position = "right",
legend.key = element_blank(),
legend.background = element_blank(),
legend.margin = margin(t = 0, b = 0, r = 15, l = 15),
legend.box = "vertical",
legend.box.margin = margin(t = 20, b = 30, r = 0, l = 0),
axis.title = element_blank(),
axis.text.x = element_text(color = "#000000", size = 16, face = "bold", angle = 45, vjust = 1, hjust = 1),
axis.text.y = element_text(color = "#000000", size = 16, face = "bold"),
axis.ticks = element_line(color = "#000000", linewidth = .3),
strip.text = element_text(colour = "#000000", size = 24, face = "bold", family = "Optima"),
strip.background = element_rect(colour = "#000000", fill = "#d6d6d6", linewidth = .3),
axis.line = element_line(colour = "#000000", linewidth = .3)) +
guides(fill = guide_legend(title = "", title.theme = element_text(size = 16, face = "bold"),
label.theme = element_text(size = 15), reverse = TRUE))
# Creates Mean_PLot ~
Mean_Plot <-
ggplot() +
geom_tile(data = subset(fulldf, Triangle == "Population"), aes(Population_1, Population_2, fill = as.numeric(Value)), colour = "#000000") +
scale_x_discrete(limits = rev, expand = c(0, 0)) +
scale_y_discrete(limits = rev, expand = c(0, 0)) +
scale_fill_gradientn(colors = rampcols, breaks = rampbreaks, limits = c(-.1, .1)) +
facet_grid(K ~ CHRType, scales = "free", space = "free") +
theme(panel.background = element_rect(fill = "#ffffff"),
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.spacing = unit(1, "lines"),
legend.position = "right",
legend.key = element_blank(),
legend.background = element_blank(),
legend.margin = margin(t = 0, b = 0, r = 15, l = 15),
legend.box = "vertical",
legend.box.margin = margin(t = 20, b = 30, r = 0, l = 0),
axis.title = element_blank(),
axis.text.x = element_text(color = "#000000", size = 16, face = "bold", angle = 45, vjust = 1, hjust = 1),
axis.text.y = element_text(color = "#000000", size = 16, face = "bold"),
axis.ticks = element_line(color = "#000000", linewidth = .3),
strip.text = element_text(colour = "#000000", size = 24, face = "bold", family = "Optima"),
strip.background = element_rect(colour = "#000000", fill = "#d6d6d6", linewidth = .3),
axis.line = element_line(colour = "#000000", linewidth = .3)) +
guides(fill = guide_legend(title = "", title.theme = element_text(size = 16, face = "bold"),
label.theme = element_text(size = 15), reverse = TRUE))
You can download a dummy fulldf from here.
Does anyone know if it is possible to replicate this behaviour in ggplot?
Many thanks in advance, George.
Here is one possible option which uses geom_polygon
to draw the triangles for the diagonal. Also note that I use a geom_point
to draw the individual plot:
fulldf <- readr::read_tsv(
"https://raw.githubusercontent.com/g-pacheco/TEMP/1b93c734472fb5282ba6a1ea7fff57fb5b3699d6/fulldf.csv"
)
library(ggplot2)
library(dplyr, warn = FALSE)
dat_ind <- fulldf |>
filter(Triangle == "Individual") |>
mutate(
x = as.numeric(factor(Population_1)),
y = as.numeric(factor(Population_2))
) |>
split(~ Population_1 + Population_2, drop = TRUE) |>
lapply(\(x) {
x |>
mutate(
x = x + .5 * scales::rescale(
as.numeric(factor(Ind_1)),
to = c(-1, 1)
),
y = y + .5 * scales::rescale(
as.numeric(factor(Ind_2)),
to = c(-1, 1)
)
)
}) |>
bind_rows()
make_polygon1 <- function(x, y, Value) {
data.frame(
x = x + .5 * c(1, 1, -1),
y = y + .5 * c(1, -1, -1),
Value = Value
)
}
dat_pop_diag <- fulldf |>
filter(Triangle == "Population", Population_1 == Population_2) |>
mutate(
x = as.numeric(factor(Population_2)),
y = as.numeric(factor(Population_1))
) |>
reframe(
make_polygon1(x, y, Value),
.by = c(Population_1, Population_2, CHRType, K)
)
make_polygon2 <- function(x, y) {
data.frame(
x = x - .5 * c(1, 1, -1),
y = y - .5 * c(1, -1, -1)
)
}
dat_ind_diag <- fulldf |>
filter(Triangle == "Population", Population_1 == Population_2) |>
mutate(
x = as.numeric(factor(Population_1)),
y = as.numeric(factor(Population_2))
) |>
reframe(
make_polygon2(x, y),
.by = c(Population_1, Population_2, CHRType, K)
)
ggplot() +
geom_polygon(
data = dat_pop_diag,
aes(x, y, group = interaction(Population_1, Population_2), fill = Value),
colour = "#000000",
linewidth = .1,
) +
geom_tile(
data = filter(fulldf, Triangle == "Population", Population_1 != Population_2),
aes(
Population_2,
Population_1,
fill = Value
), colour = "#000000"
) +
# Individual plot
geom_point(
data = dat_ind,
aes(
x, y,
color = Value
),
size = .25,
shape = 15
) +
# Upper Triangle Grid
geom_tile(
data = filter(fulldf, Triangle == "Population", Population_1 != Population_2),
aes(Population_1, Population_2), fill = NA, colour = "#000000"
) +
geom_polygon(
data = dat_ind_diag,
aes(x, y, group = interaction(Population_1, Population_2)),
colour = alpha("#000000", .7),
linewidth = .1,
fill = NA
) +
scale_x_discrete(expand = c(0, 0)) +
scale_y_discrete(expand = c(0, 0)) +
scale_fill_gradientn(
colors = rampcols, breaks = rampbreaks, limits = c(-.1, .1),
aesthetics = c("color", "fill"),
guide = guide_legend(
title = "", title.theme = element_text(size = 16, face = "bold"),
label.theme = element_text(size = 15), reverse = TRUE
),
na.value = "transparent"
) +
facet_grid(K ~ CHRType, scales = "free", space = "free") +
theme(
axis.text.x = element_text(angle = 90)
)