Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add text labels to a ggplot2 mosaic plot

Using the following data:

Category <- c("Bankpass", "Bankpass", "Bankpass", "Moving", "Moving")
Subcategory <- c("Stolen", "Lost", "Login", "Address", "New contract")
Weight <- c(10,20,13,40,20)
Duration <- as.character(c(0.2,0.4,0.5,0.44,0.66))
Silence <- as.character(c(0.1,0.3,0.25,0.74,0.26))
df <- data.frame(Category, Subcategory, Weight, Duration, Silence)

Which I use to create the following mosaic plot:

library (ggplot2)
library (ggmosaic)

g <- ggplot(data = df) +
  geom_mosaic(aes(weight = Weight, x = product(Category), fill = Duration), 
              offset = 0, na.rm = TRUE) +  
  theme(axis.text.x = element_text(angle = -25, hjust = .1)) +
  theme(axis.title.x = element_blank()) +
  scale_fill_manual(values = c("#e8f5e9", "#c8e6c9", "#a5d6a7", "#81c784", "#66bb6a"))

enter image description here

This works, however I would like to include text labels on the elements on the graph ("Showing fe stolen, lost" etc.)

However, when I do:

g + geom_text(x = Category, y = Subcategory, label = Weight)

I get the following error:

Error in UseMethod("rescale") : no applicable method for 'rescale' applied to an object of class "character"

Any thoughts on what goes wrong here?

like image 627
Henk Straten Avatar asked Dec 31 '17 10:12

Henk Straten


People also ask

Which argument can be used to add labels in Ggplot?

Method 1: Using geom_text() This method is used to add Text labels to data points in ggplot2 plots.

How do you make a mosaic plot in ggplot2?

To create a mosaic plot using base ggplot2, we would need to compute the respective x and y values for each rectangle. We represent states along the y-axis and Product Categories along the x-axis. We calculate the respective xmin, xmax, ymin and ymax of the by grouping by Product Categories and States.

What is Geom_mosaic?

Designed to create visualizations of categorical data, geom_mosaic() has the capability to produce bar charts, stacked bar charts, mosaic plots, and double decker plots and therefore offers a wide range of potential plots. The plots below highlight the package's versatility.


2 Answers

Here is my attempt. The x-axis is in a discrete variable (i.e., Category). So you cannot use it in geom_text(). You somehow need to create a numeric variable for the axis. Similarly, you need to find position in the y-axis for labels. In order to get numeric values for the two dimensions, I decided to access to the data frame staying behind your graphic. When you use the ggmosaic package, there is one data frame behind a graphic in this case. You can get it using ggplot_build(). You can calculate x and y values using the information in the data frame (e.g., xmin, and xmax). This is good news. But, we have bad news too. When you reach the data, you realize that there is no information about Subcategory that you need for labels.

We can overcome this challenge joining the data frame above with the original data. When I joined the data, I calculated proportion for both the original data and the other data. The values are purposely converted to character. temp is the data set you need in order to add labels.

library(dplyr)
library(ggplot2)
library(ggmosaic)

# Add proportion for each and convert to character for join

df <- group_by(df, Category) %>%
      mutate(prop = as.character(round(Weight / sum(Weight),3)))

# Add proportion for each and convert to character.
# Get x and y values for positions
# Use prop for join

temp <- ggplot_build(g)$data %>%
        as.data.frame %>%
        transmute(prop = as.character(round(ymax - ymin, 3)),
                  x.position = (xmax + xmin) / 2,
                  y.position = (ymax + ymin) / 2) %>%
        right_join(df)

g + geom_text(x = temp$x.position, y = temp$y.position, label = temp$Subcategory) 

enter image description here

like image 89
jazzurro Avatar answered Sep 24 '22 01:09

jazzurro


I think you are looking for something like this

library(ggplot2)
library(ggmosaic)

Your data:

Category <- c("Bankpass", "Bankpass", "Bankpass", "Moving", "Moving")
Subcategory <- c("Stolen", "Lost", "Login", "Address", "New contract")
Weight <- c(10,20,13,40,20)
Duration <- as.character(c(0.2,0.4,0.5,0.44,0.66))
Silence <- as.character(c(0.1,0.3,0.25,0.74,0.26))
mydf <- data.frame(Category, Subcategory, Weight, Duration, Silence)

ggplot(data = mydf) +
    geom_mosaic(aes( x = product(Duration, Subcategory), fill=factor(Duration)), na.rm=TRUE) + 
    theme(axis.text.x=element_text(angle=-25, hjust= .1)) +
    labs(x="Subcategory", title='f(Duration, Subcategory | Category)')  + 
    facet_grid(Category~.) + 
    guides(fill=guide_legend(title = "Duration", reverse = TRUE))

The output is:

enter image description here

It is almost the best you can do on ggmosaic package. You should try other packages.

Good luck for your project work ;-)

like image 45
Scipione Sarlo Avatar answered Sep 27 '22 01:09

Scipione Sarlo