MoonS
MoonS

Reputation: 175

Multiple values in one tile with geom_tile

I'm creating a matrix plot with geom_tile, but seeing that rows have multiple values that are overlaid in the plot. Is there a way to fill each tile with the multiple colors represented for that entry? Perhaps similar to this (ideally the shapes would be rectangular and not triangular): split fill in ggplot geom_tile (or heatmap): two colors by third value

enter image description here

Code:

# Create color palette

par(mar=c(0,0,1,0))

coul <- brewer.pal(9, "Set3") 

ggplot(plot_data, aes(x = from, y = to, fill = agreement_num)) +
  geom_tile() +
  scale_fill_manual(values = coul) +
  theme_bw() +
  scale_x_discrete(drop = FALSE) +
  scale_y_discrete(drop = FALSE) +
  theme(
    axis.text.x = element_text(size = 9,angle = 270, hjust = 0,vjust=0),
    axis.text.y = element_text(size = 9),
    aspect.ratio = 1)

Reproducible example:

plot_data <- structure(list(from = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, NA, NA, NA, NA), levels = c("Afghanistan", 
"Kazakhstan", "Kyrgyzstan", "Tajikistan", "Turkmenistan", "Uzbekistan"
), class = "factor"), to = structure(c(1L, 3L, 3L, 3L, 3L, 3L, 
3L, 4L, 4L, 4L, 5L, 5L, 6L, 6L, 2L, 6L, NA, NA, NA, NA), levels = c("Afghanistan", 
"Kazakhstan", "Kyrgyzstan", "Tajikistan", "Turkmenistan", "Uzbekistan"
), class = "factor"), weight = c(1291072130433.34, 480160896152.234, 
480160896152.234, 480160896152.234, 480160896152.234, 480160896152.234, 
480160896152.234, 3474907531417.02, 3474907531417.02, 3474907531417.02, 
867103764128.709, 867103764128.709, 7791981051421.92, 7791981051421.92, 
133799551.098735, 1102379004.66647, NA, NA, NA, NA), agreement_num = structure(c(NA, 
1L, 5L, 2L, 6L, 3L, 4L, 2L, 1L, 6L, 1L, 6L, 1L, 6L, NA, NA, NA, 
NA, NA, NA), levels = c("51", "58", "133", "135", "176", "224"
), class = "factor")), row.names = c("1", "2", "3", "4", "5", 
"6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", 
"NA", "NA.1", "NA.2", "NA.3"), class = "data.frame")

Upvotes: 1

Views: 214

Answers (1)

stefan
stefan

Reputation: 125897

One option would be to use a geom_rect and some manual computation to draw multiple rects per tile:

library(ggplot2)
library(dplyr, warn = FALSE)

plot_data <- plot_data |>
  mutate(
    x = as.numeric(from),
    y = as.numeric(to),
    ymin = y - .5, ymax = y + .5
  ) |>
  mutate(
    n = n(),
    xmin = x + scales::rescale(row_number(),
      from = c(1, unique(n) + 1),
      to = .5 * c(-1, 1)
    ),
    xmax = x + scales::rescale(row_number() + 1,
      from = c(1, unique(n) + 1),
      to = .5 * c(-1, 1)
    ),
    .by = c(from, to)
  )

coul <- RColorBrewer::brewer.pal(9, "Set3") 

ggplot(plot_data, aes(x = from, y = to, fill = agreement_num)) +
  geom_rect(
    aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax)
  ) +
  scale_fill_manual(values = coul) +
  theme_bw() +
  scale_x_discrete(drop = FALSE) +
  scale_y_discrete(drop = FALSE) +
  theme(
    axis.text.x = element_text(
      size = 9, angle = 270,
      hjust = 0, vjust = 0
    ),
    axis.text.y = element_text(size = 9),
    aspect.ratio = 1
  )
#> Warning: Removed 4 rows containing missing values (`geom_rect()`).

Upvotes: 1

Related Questions