How can I create a mosaic plot as shown in pic below

169 views Asked by At

I have been trying for days to create a mosaic plot using land cover data but I was not able to figure it out, I am using this data :

enter image description here

I would like to create something like this:

enter image description here

Thanks in advance!

Zack

1

There are 1 answers

3
TarJae On

Update: Here is the code: You can facet_wrap by year or not:

library(tidyverse)

# data
df <- tibble::tribble(
~A,     ~B,    ~C,     ~D,     ~E,
"LC",   2002,  2004,   2006,   2008,
"class1",  27.05, 25.35,  13.35,  21.35,
"class2",   60.2,  42.5,  53.05,  72.95,
"class3",  33.45, 59.75,   49.2,     62,
"class4", 198.15, 168.1, 193.95, 136.55,
"class5",  48.55,  65.3,  54.65,  10.35,
"class6",   59.6,    37,   44.7,  94.75
  )

# wrangle dataframe
df1 <- df %>% 
  rename("LC" = "A", `2002` = B, `2004` = C, 
         `2006` = D, `2008` = E) %>%          # rename colnames
  slice(-1) %>%                               # remove first row
  mutate(id = row_number()) %>%               # create id
  pivot_longer(
    cols = c(-id,-LC),
    names_to = "year",
    values_to = "value"
  ) %>%                                       # bring into long format
  mutate(LC = as.factor(LC),
         year = as.factor(year)
         )                                    # transform to factor



#  calculate the respective xmin, xmax, ymin and ymax of the by grouping by LC and year
df_mosaic <- df1 %>% group_by(LC) %>%
  mutate(
    share = value / sum(value),
    tot_group = sum(value)
  ) %>% 
  ungroup()

df_mosaic1 <- df_mosaic %>%
  group_by(year) %>%
  arrange(desc(LC)) %>%
  mutate(
    ymax = cumsum(tot_group) / sum(tot_group),
    ymin = (ymax - (tot_group/sum(tot_group)))
  ) %>% ungroup() %>%
  group_by(LC) %>%
  arrange(desc(year)) %>%
  mutate(xmax = cumsum(share), xmin = xmax - share) %>%
  ungroup() %>%
  arrange(year)

# labels
labels <- df_mosaic1 %>%
  filter(year == "2008") %>%
  mutate(y = ymax - 0.01, yRange = (ymax - ymin)* 100) %>%
  select(LC, xmax, y, yRange) %>%
  ungroup()

value_labels <- df_mosaic1 %>%
  select(LC, year, xmin, xmax, ymax, share) %>%
  mutate(
    x = ifelse(year == "2008", xmax, xmin),
    y = ymax - 0.005,
    label = paste0(round(share * 100), "%"),
    hjust = ifelse(year == "2008", 1.05, -0.25)
  )

# mosaic plot
ggplot(df_mosaic1) +
  geom_rect(aes(ymin = ymin, ymax = ymax, xmin = xmin, xmax = xmax,
                fill = year), colour = "white", size = 0.2)+
  scale_fill_manual("legend", values = c("2002" = "blue",
                                         "2004" = "red",
                                         "2006" = "grey","2008"="brown"))+
  theme_light()+
  geom_text(
    data = labels,
    aes(x = 1.05, y = y, label = as.character(LC)),
    hjust = 0, vjust = 1, colour = "blue",size=3
  ) +
  geom_text(
    data = value_labels,
    aes(x = x, y = y, label = label, hjust = hjust),
    vjust = 1, size = 3, alpha = 1, colour = "white"
  ) +
  scale_y_continuous( breaks = labels$y, limits = c(0, 1),
                      labels = scales::percent)+
  facet_wrap(~ year) +
  theme_minimal()+
  theme(axis.title=element_blank(),
        plot.title = element_text(hjust = 0.5))+
  ggtitle("Values by Year and Class")

enter image description here

First answer: I can provide the code for this kind of mosaic plot. It is not the same as your example. Please tell me if this one is what may help you: enter image description here