0

I wish to create an triangular matrix, rotate it 45 degrees clockwise, and attach color bars on the sides of the rotated triangular matrix. Here is my code:

# The data
library(tidyverse)

x <- 1:10
y <- 1:10
data <- expand.grid(X=x, Y=y)
data$X <- as.numeric(data$X)
data$Y <- as.numeric(data$Y)
data$Z <- 1:(10*10)

# Create upper triangular matrix
zz <- t(matrix(data$Z, 10, 10))
zz[lower.tri(zz)] <- NA
data$zz <- c(t(zz))

# Use "-Y" so that the first row of data is plotted in the first row
p1 <- ggplot(data, aes(X, -Y, fill= zz)) + 
  geom_tile() +
  # scale_fill_gradient(low="blue", high="red") +
  scale_fill_gradient(low = "#132B43", high = "#56B1F7", space = "Lab", na.value="white") +
  theme_bw() +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_blank(),
        panel.background = element_blank())

This is p1, which looks fine: enter image description here

I wish to rotate this matrix 45 degrees clockwide. I did so following the suggested code here:

rotate <- function(df, degree) {
  dfr <- df
  degree <- pi * degree / 180
  l <- sqrt(df$X^2 + df$Y^2)
  teta <- atan(df$Y / df$X)
  dfr$X <- round(l * cos(teta - degree))
  dfr$Y <- round(l * sin(teta - degree))
  return(dfr)
}

data_rot <- rotate(data, 45)

p2 <- ggplot(data_rot, aes(X, -Y, fill= zz)) + 
  geom_tile() +
  # scale_fill_gradient(low="white", high="blue") +
  scale_fill_gradient(low = "#132B43", high = "#56B1F7", space = "Lab", na.value="white") +
  theme_bw() +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_blank(),
        panel.background = element_blank())

However, p2 is not what I want: enter image description here

Here is what I want: enter image description here

Since I wish to rotate p1 45 degrees clockwise, the diagonal should be verticle and there should not be missing value inside the triangular matrix. How to do the rotation?

Additionally, I want to add color bars by sides of the heatmap, as shown by the pink circled color bars in the figure below: enter image description here

My data has 10 columns and 10 rows, I wish to plot color bars like above for my own heatmap using 5 different colors, with each color spanning two adjacent rows/columns. How to add?

Patrick
  • 1,057
  • 9
  • 23

2 Answers2

1
p1_fmt <- p1 + guides(fill = "none") + coord_equal()
tri_file <- tempfile()
ggsave(tri_file, p1_fmt, width = 3, height = 3, device = "png")

p1_guide <- cowplot::get_legend(p1)
guide_file <- tempfile()
ggsave(guide_file, p1_guide, width = 1, height = 1.5, device = "png")


library(magick)
tri <- image_read(tri_file) %>%
  image_rotate(45) %>%
  image_trim()
guide <- image_read(guide_file)

image_append(c(tri, guide))

enter image description here

Jon Spring
  • 55,165
  • 4
  • 35
  • 53
0
zz %>%
  as.data.frame() %>%
  mutate(row = 11 - row_number()) %>%
  pivot_longer(-row, names_to = "col") %>%
  filter(!is.na(value)) %>%
  # slice(1:12) %>%
  mutate(col = parse_number(col),
         col_new = col - 5 - (row+col)/2,
         row_new = row - (10 - col)) %>% 
  ggplot(aes(col_new, row_new, fill = value)) +
  geom_tile(width = 1) 

enter image description here

Jon Spring
  • 55,165
  • 4
  • 35
  • 53
  • Since I wish to rotate `p1` 45 deg clockwise, the diagonal should be verticle. I added a new plot showing how the output should look like. Thx. – Patrick Oct 17 '21 at 04:07