Different colors with gradient for subgroups on a treemap ggplot2 R
Asked Answered
H

2

9

I have a treemap plot (shown below). The only change that I want to have is to change the color of subgroup (YEAR in the plot) to different colors, not all blue. Is this possible at all?

Sample data frame

PL <- c(rep("PL1", 4), repl("PL2", 4), rep("PL3", 4), rep("PL4", 4))
CNT <- sample(seq(1:50), 16)
YEAR <- rep(c("2015", "2016", "2017", "2018"), 4)

df <- data.frame(PL, YEAR, CNT)

Plot

PL <- c(rep("PL1", 4), repl("PL2", 4), rep("PL3", 4), rep("PL4", 4))
    CNT <- sample(seq(1:50), 16)
    YEAR <- rep(c("2015", "2016", "2017", "2018"), 4)

    df <- data.frame(PL, YEAR, CNT)

    # plot
library(ggplot2)
library(treemapify)
treeMapPlot <- ggplot(df, aes(area = CNT,
                              fill = CNT,
                              label=PL, 
                              subgroup=YEAR)) +
      geom_treemap() +
      geom_treemap_subgroup_border(colour = "white") +
      geom_treemap_text(fontface = "italic",
                        colour = "white",
                        place = "centre",
                        grow = F,
                        reflow = T) +
      geom_treemap_subgroup_text(place = "centre",
                                 grow = T,
                                 alpha = 0.5,
                                 colour = "#FAFAFA",
                                 min.size = 0)

treeMapPlot

Treemap Plot

If I change the fill in aes I can get this, but I lose the gradient. I need to keep these colors, but show the tiles with gradient color, meaning small CNT lighter, larger CNT darker

treeMapPlot <- ggplot(df, aes(area = CNT,
                              fill = YEAR,
                              label = PL, 
                              subgroup = YEAR))

enter image description here

Hayley answered 3/5, 2018 at 20:6 Comment(10)
You're not going to be able to map fill to 4 different gradients (dark to light for each of those 4 colors). Instead, you can keep fill based on year, and map alpha onto count to simulate lighter colors where the count is lowerGendron
@Gendron could you please show me where I should put it?Hayley
@Gendron using alpha is not beautiful indeed, cannot we apply sth similar to this: #24618397Hayley
Oh interesting! What they did was layer the same geom twice, so you could do one geom_treemap(fill = "black"), then geom_treemap(aes(alpha = CNT)) or something like that. I'll mess around with itGendron
@Gendron it gives me this error: Error: Aesthetics must be either length 1 or the same as the data (12): area, label, subgroupHayley
For the bottom layer, fill shouldn't be inside an aes. It worked for me with two separate geom_treemap callsGendron
@Gendron I copy pasted from your comment, there should be a mistake somewhereHayley
treeMapPlot <- ggplot(df, aes(area = CNT, fill = YEAR, label=PL, subgroup=YEAR)) + geom_treemap(fill = "black") + geom_treemap(aes(alpha = CNT))+ geom_treemap_subgroup_border(colour="white") +Hayley
geom_treemap_text(fontface = "italic", colour = "white", place = "centre", grow = F, reflow=T) + geom_treemap_subgroup_text(place = "centre", grow = T, alpha = 0.5, colour = "#FAFAFA", min.size = 0)+ scale_alpha_continuous(range = c(0.5,1))Hayley
I'll just amend my answerGendron
G
6

It's not the most beautiful solution, but mapping count to alpha simulates a light-to-dark gradient for each color. Add aes(alpha = CNT) inside geom_treemap, and scale alpha however you want.

library(ggplot2)
library(treemapify)

PL <- c(rep("PL1",4),rep("PL2",4),rep("PL3",4),rep("PL4",4))
CNT <- sample(seq(1:50),16)
YEAR <- rep(c("2015","2016","2017","2018"),4)

df <- data.frame(PL,YEAR,CNT)

ggplot(df, aes(area = CNT, fill = YEAR, label=PL, subgroup=YEAR)) +

# change this line
    geom_treemap(aes(alpha = CNT)) +
    geom_treemap_subgroup_border(colour="white") +
    geom_treemap_text(fontface = "italic",
                                        colour = "white",
                                        place = "centre",
                                        grow = F,
                                        reflow=T) +
    geom_treemap_subgroup_text(place = "centre",
                                                         grow = T,
                                                         alpha = 0.5,
                                                         colour = "#FAFAFA",
                                                         min.size = 0) +
    scale_alpha_continuous(range = c(0.2, 1))

Created on 2018-05-03 by the reprex package (v0.2.0).

Edit to add: Based on this post on hacking faux-gradients by putting an alpha-scaled layer on top of a layer with a darker fill. Here I've used two geom_treemaps, one with fill = "black", and one with the alpha scaling. Still leaves something to be desired.

ggplot(df, aes(area = CNT, fill = YEAR, label=PL, subgroup=YEAR)) +
    geom_treemap(fill = "black") +
    geom_treemap(aes(alpha = CNT)) +
    geom_treemap_subgroup_border(colour="white") +
    geom_treemap_text(fontface = "italic",
                                        colour = "white",
                                        place = "centre",
                                        grow = F,
                                        reflow=T) +
    geom_treemap_subgroup_text(place = "centre",
                                                         grow = T,
                                                         alpha = 0.5,
                                                         colour = "#FAFAFA",
                                                         min.size = 0) +
    scale_alpha_continuous(range = c(0.4, 1))

Created on 2018-05-03 by the reprex package (v0.2.0).

Gendron answered 3/5, 2018 at 20:34 Comment(2)
The good thing about this method is simplicity and being dynamic, @Gendron meaning that I have my data coming from a database and all of these variables can change over time, which won't break the code, however still the colors are not real vivacious as Claus's method offers. It was a good challenge though. Thanks!Hayley
NOTE: if the code throws an error it is most likely a library conflict so to fix it call the functions explicitly like this: treemapify::geom_treemapHayley
P
17

One option is to calculate the colors separately for each cell and then just plot them directly. This doesn't give you a legend, but arguably a legend isn't that useful anyways. (You'd need 4 separate legends, and those could be made and added to the plot if needed.)

library(ggplot2)
library(treemapify)

set.seed(342)
PL <- c(rep("PL1", 4), rep("PL2", 4), rep("PL3", 4), rep("PL4", 4))
CNT <- sample(seq(1:50), 16)
YEAR <- rep(c("2015", "2016", "2017", "2018"), 4)

df <- data.frame(PL, YEAR, CNT)

# code to add colors to data frame follows
# first the additional packages needed
library(dplyr)
library(colorspace)  # install via: install.packages("colorspace", repos = "http://R-Forge.R-project.org")
library(scales)

# I'll use 4 palettes from the colorspace package, one for each year
palette <- rep(c("Teal", "Red-Yellow", "Greens", "Purples"), 4)

# We add the palette names and then calculate the colors for each
# data point. Two notes:
#  - we scale the colors to the maximum CNT in each year
#  - we're calculating 6 colors but use only 5 to make the gradient;
#    this removes the lightest color
df2 <- mutate(df,
              palette = palette) %>%
  group_by(palette) %>%
  mutate(
    max_CNT = max(CNT),
    color = gradient_n_pal(sequential_hcl(6, palette = palette)[1:5])(CNT/max_CNT))


ggplot(df2, aes(area = CNT, fill = color, label=PL, subgroup=YEAR)) +
  geom_treemap() +
  geom_treemap_subgroup_border(colour="white") +
  geom_treemap_text(fontface = "italic",
                    colour = "white",
                    place = "centre",
                    grow = F,
                    reflow=T) +
  geom_treemap_subgroup_text(place = "centre",
                             grow = T,
                             alpha = 0.5,
                             colour = "#FAFAFA",
                             min.size = 0) +
  scale_fill_identity()

enter image description here

It's also possible to generate color scales dynamically if you don't know ahead of time how many cases there will be:

library(ggplot2)
library(treemapify)

set.seed(341)
PL <- c(rep("PL1", 6), rep("PL2", 6), rep("PL3", 6), rep("PL4", 6))
CNT <- sample(seq(1:50), 24)
YEAR <- rep(c("2013", "2014", "2015", "2016", "2017", "2018"), 4)

df <- data.frame(PL, YEAR, CNT)

# code to add colors to data frame follows
# first the additional packages needed
library(dplyr)
library(colorspace)  # install via: install.packages("colorspace", repos = "http://R-Forge.R-project.org")
library(scales)

# number of palettes needed
n <- length(unique(YEAR))

# now calculate the colors for each data point
df2 <- df %>%
  mutate(index = as.numeric(factor(YEAR))- 1) %>%
  group_by(index) %>%
  mutate(
    max_CNT = max(CNT),
    color = gradient_n_pal(
      sequential_hcl(
        6,
        h = 360 * index[1]/n,
        c = c(45, 20),
        l = c(30, 80),
        power = .5)
      )(CNT/max_CNT)
    )

ggplot(df2, aes(area = CNT, fill = color, label=PL, subgroup=YEAR)) +
  geom_treemap() +
  geom_treemap_subgroup_border(colour="white") +
  geom_treemap_text(fontface = "italic",
                    colour = "white",
                    place = "centre",
                    grow = F,
                    reflow=T) +
  geom_treemap_subgroup_text(place = "centre",
                             grow = T,
                             alpha = 0.5,
                             colour = "#FAFAFA",
                             min.size = 0) +
  scale_fill_identity()

enter image description here

Finally, you can manually define the hues of the color scales:

library(ggplot2)
library(treemapify)

set.seed(341)
PL <- c(rep("PL1", 6), rep("PL2", 6), rep("PL3", 6), rep("PL4", 6))
CNT <- sample(seq(1:50), 24)
YEAR <- rep(c("2013", "2014", "2015", "2016", "2017", "2018"), 4)

df <- data.frame(PL, YEAR, CNT)

# code to add colors to data frame follows
# first the additional packages needed
library(dplyr)
library(colorspace)  # install via: install.packages("colorspace", repos = "http://R-Forge.R-project.org")
library(scales)

# each color scale is defined by a hue, a number between 0 and 360
hues <- c(300, 50, 250, 100, 200, 150)

# now calculate the colors for each data point
df2 <- df %>%
  mutate(index = as.numeric(factor(YEAR))) %>%
  group_by(index) %>%
  mutate(
    max_CNT = max(CNT),
    color = gradient_n_pal(
      sequential_hcl(
        6,
        h = hues[index[1]],
        c = c(45, 20),
        l = c(30, 80),
        power = .5)
    )(CNT/max_CNT)
  )

ggplot(df2, aes(area = CNT, fill = color, label=PL, subgroup=YEAR)) +
  geom_treemap() +
  geom_treemap_subgroup_border(colour="white") +
  geom_treemap_text(fontface = "italic",
                    colour = "white",
                    place = "centre",
                    grow = F,
                    reflow=T) +
  geom_treemap_subgroup_text(place = "centre",
                             grow = T,
                             alpha = 0.5,
                             colour = "#FAFAFA",
                             min.size = 0) +
  scale_fill_identity()

enter image description here

Porphyria answered 3/5, 2018 at 23:0 Comment(0)
G
6

It's not the most beautiful solution, but mapping count to alpha simulates a light-to-dark gradient for each color. Add aes(alpha = CNT) inside geom_treemap, and scale alpha however you want.

library(ggplot2)
library(treemapify)

PL <- c(rep("PL1",4),rep("PL2",4),rep("PL3",4),rep("PL4",4))
CNT <- sample(seq(1:50),16)
YEAR <- rep(c("2015","2016","2017","2018"),4)

df <- data.frame(PL,YEAR,CNT)

ggplot(df, aes(area = CNT, fill = YEAR, label=PL, subgroup=YEAR)) +

# change this line
    geom_treemap(aes(alpha = CNT)) +
    geom_treemap_subgroup_border(colour="white") +
    geom_treemap_text(fontface = "italic",
                                        colour = "white",
                                        place = "centre",
                                        grow = F,
                                        reflow=T) +
    geom_treemap_subgroup_text(place = "centre",
                                                         grow = T,
                                                         alpha = 0.5,
                                                         colour = "#FAFAFA",
                                                         min.size = 0) +
    scale_alpha_continuous(range = c(0.2, 1))

Created on 2018-05-03 by the reprex package (v0.2.0).

Edit to add: Based on this post on hacking faux-gradients by putting an alpha-scaled layer on top of a layer with a darker fill. Here I've used two geom_treemaps, one with fill = "black", and one with the alpha scaling. Still leaves something to be desired.

ggplot(df, aes(area = CNT, fill = YEAR, label=PL, subgroup=YEAR)) +
    geom_treemap(fill = "black") +
    geom_treemap(aes(alpha = CNT)) +
    geom_treemap_subgroup_border(colour="white") +
    geom_treemap_text(fontface = "italic",
                                        colour = "white",
                                        place = "centre",
                                        grow = F,
                                        reflow=T) +
    geom_treemap_subgroup_text(place = "centre",
                                                         grow = T,
                                                         alpha = 0.5,
                                                         colour = "#FAFAFA",
                                                         min.size = 0) +
    scale_alpha_continuous(range = c(0.4, 1))

Created on 2018-05-03 by the reprex package (v0.2.0).

Gendron answered 3/5, 2018 at 20:34 Comment(2)
The good thing about this method is simplicity and being dynamic, @Gendron meaning that I have my data coming from a database and all of these variables can change over time, which won't break the code, however still the colors are not real vivacious as Claus's method offers. It was a good challenge though. Thanks!Hayley
NOTE: if the code throws an error it is most likely a library conflict so to fix it call the functions explicitly like this: treemapify::geom_treemapHayley

© 2022 - 2024 — McMap. All rights reserved.