Home > Blockchain >  Plotting a better treemap using ggplot and the geom_rect hack, but how to get the labels correct?
Plotting a better treemap using ggplot and the geom_rect hack, but how to get the labels correct?

Time:02-11

I have found it challenging to create a treemap using ggplot, and treemap_output

Using the workaround in this blog, but adding an additional hierarchy and wanted to change the labeling is where the problem comes in.

# Create the plot in ggplot using geom_rect

# Get underlying data created from running treemap
tm_plot_data <- tree_p$tm %>% 
  mutate(x1 = x0   w,
         y1 = y0   h) %>% 
  mutate(x = (x0 x1)/2,
         y = (y0 y1)/2) %>% 
  mutate(
    primary_group = case_when(
      level == 1 ~ 1.5,
      level == 2 ~ 0.75,
      TRUE       ~ 0.5
    )
  ) 



# Plot
ggplot(tm_plot_data, aes(xmin = x0, ymin = y0, xmax = x1, ymax = y1))   
  # add fill and borders for groups and subgroups
  geom_rect(aes(fill = color, size = primary_group),
            show.legend = FALSE,
            color       = "black",
            alpha       = 0.3
  )  
  scale_fill_identity()  
  # set thicker lines for group borders
  scale_size(range = range(tm_plot_data$primary_group))  
  # add labels
  ggfittext::geom_fit_text(aes(label = my_segment), color = "white", min.size = 1)  
  ggfittext::geom_fit_text(aes(label = my_class), color = "blue", min.size = 1)  
  ggfittext::geom_fit_text(aes(label = my_type), color = "red", min.size = 1)  
  # options
  scale_x_continuous(expand = c(0, 0))  
  scale_y_continuous(expand = c(0, 0))  
  theme_void()

treemap_hack

So the question I have is there a way to create the labeling like treemap? Specifically, seg_a, seg_b, and seg_c should only appear once, centered over the area of their respective segments. I'd also like to move the labels so that they do not overlap

Thanks for any help and suggestions!

CodePudding user response:

The issue is that you use your full dataset tm_plot_data to add the labels. Hence, for each upper level you you get multiple labels. To solve this issue aggregate your datasets and pass these datasets as data to ggfittext::geom_fit_text. To deal with overlapping labels you could e.g. use the place argument of ggfittext::geom_fit_text to move the class labels to the bottom left and the type labels to the topright.

library(tidyverse)
library(treemap)

set.seed(123)

tm_seg <- tm_plot_data %>% 
  group_by(my_segment) %>% 
  summarise(x0 = min(x0), y0 = min(y0), y1 = max(y1), x1 = max(x1)) %>% 
  ungroup()

tm_class <- tm_plot_data %>% 
  group_by(my_segment, my_class) %>% 
  summarise(x0 = min(x0), y0 = min(y0), y1 = max(y1), x1 = max(x1)) %>% 
  ungroup()

tm_type <- tm_plot_data %>% 
  group_by(my_segment, my_class, my_type) %>% 
  summarise(x0 = min(x0), y0 = min(y0), y1 = max(y1), x1 = max(x1)) %>% 
  ungroup()

# Plot
ggplot(tm_plot_data, aes(xmin = x0, ymin = y0, xmax = x1, ymax = y1))  
  # add fill and borders for groups and subgroups
  geom_rect(aes(fill = color, size = primary_group),
    show.legend = FALSE,
    color       = "black",
    alpha       = 0.3
  )  
  scale_fill_identity()  
  # set thicker lines for group borders
  scale_size(range = range(tm_plot_data$primary_group))  
  # add labels
  ggfittext::geom_fit_text(data = tm_seg, aes(label = my_segment), color = "white", min.size = 4)  
  ggfittext::geom_fit_text(data = tm_class, aes(label = my_class), color = "blue", min.size = 1, place = "bottomleft")  
  ggfittext::geom_fit_text(data = tm_type, aes(label = my_type), color = "red", min.size = 1, place = "topright")  
  # options
  scale_x_continuous(expand = c(0, 0))  
  scale_y_continuous(expand = c(0, 0))  
  theme_void()
#> Warning: Removed 3 rows containing missing values (geom_fit_text).
#> Warning: Removed 12 rows containing missing values (geom_fit_text).

  • Related