rplotmosaic-plot

Add labels to a mosaic plot in R


I have the following table x which looks like this:

> x <- table(married_working_women$fem_ed, married_working_women$hom_ed)
> rownames(x) <- c("< HS", "HS", "> HS")
> colnames(x) <- c("< HS", "HS", "> HS")
> x
      
       < HS   HS > HS
  < HS 2410  112  283
  HS     63   83   55
  > HS   44   49  172

I create the Mosaic plot using the following code:

library(RColorBrewer)

mosaicplot(x,
           main = "Education Levels of Working Spouses",
           xlab = "Wife's Education",
           ylab = "Husband's Education",
           las = 1, color = brewer.pal(3, name = "Pastel2"))

which gives this result:

enter image description here

Now I want to add the numbers in the table x, and maybe also the percentages, to the mosaic plot. Here is an example:

enter image description here

I tried to use mosaic function, but it gives an error:

> library(vcd)
> mosaic(x, labeling = labeling_cells(text = round(x, 2)), legend = TRUE)
Error in `[.default`(c(2410, 63, 44, 112, 83, 49, 283, 55, 172), `NA` = NA_character_,  : 
  subscript out of bounds

Can someone please give me a hint as to how to add labels to the mosaicplot function? Thank you very much in advance.


Solution

  • I'm not sure why, but the key was to never use colnames(x) and rownames(x). You should use dimnames(x) instead when creating your table. Code was based on this RStudio post and this StackOverflow post.

    library(tidyverse)
    library(RColorBrewer)
    library(vcd)
    
    x <- read_delim("
    2410 112 283
    63 83 55
    44 49 172", col_names = FALSE)
    x <- as.table(as.matrix(x))
    
    dimnames(x) <- list(A = c("< HS", "HS", "> HS"),
                        B = c("< HS", "HS", "> HS")) 
    percentages <- round(100*prop.table(x), 3)
    txt <- as.table(matrix(paste0(x, "; ", percentages, "%"), 3, 3))
    dimnames(txt) <- dimnames(x)
    
    vcd::mosaic(x, pop = F, shade = T, colorize = T, 
                gp = gpar(fill = matrix(c("grey", "green", "red", "blue", "yellow", "blue", "red", "green", "grey"),  3, 3)))
    
    labeling_cells(text = txt, margin = 0)(x)
    

    enter image description here