Hot questions for Using Ggplot2 in ggmosaic

Question:

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"))

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?


Answer:

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) 

Question:

I'm playing around with the geom_mosaic() function (part of the ggmosaic package) on R Shiny and came up with a problem I've been trying to solve for a few days.

First, some sample data:

a <- "a"
b <- "b" 
c <- "c"

df <- tribble(
  ~id, ~var1, ~var2, ~var3, 
  1, a, b, c,
  2, b, b, c,
  3, b, b, c,
  4, a, c, b, 
  5, a, a, a,
  6, b, c, c, 
  7, b, c, a,
  8, a, a, b,
  9, a, a, a, 
  10, b, b, c
)

It seems that geom_mosaic() isn't accepting reactive inputs on Shiny, i.e. Code 1 (below) works fine on the R console, but Code 2 (the R Shiny equivalent) isn't working, giving the following Error message:

Error: object ______ not found

Code 1 (geom_mosaic works fine on console):

library(tidyverse)
library(ggmosaic)

selected_var1 <- "var1"
selected_var1_dat <- df[[selected_var1]]

selected_var2 <- "var2"
selected_var2_dat <- df[[selected_var2]]

ggplot(data = df) + 
  geom_mosaic(aes(x = product(selected_var1_dat), 
                  fill = selected_var2_dat, na.rm = T))

Output ggplot (everything looks good):

Code 2 (now, to implement in Shiny):

library(shiny) 
library(tidyverse)
library(ggmosaic)

varOptions <- c("var1", "var2", "var3")
a <- "a"
b <- "b"
c <- "c"

df <- tribble(
  ~id, ~var1, ~var2, ~var3, 
  1, a, b, c,
  2, b, b, c,
  3, b, b, c,
  4, a, c, b, 
  5, a, a, a,
  6, b, c, c, 
  7, b, c, a,
  8, a, a, b,
  9, a, a, a, 
  10, b, b, c
)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "selected_var1",
                  label = "X:",
                  choices = varOptions),
      selectInput(inputId = "selected_var2",
                  label = "Y:", 
                  choices = varOptions)
    ),
    mainPanel(
      plotlyOutput(outputId = "mosaic")
    )
  )
)

server <- function(input, output) {
  output$mosaic <- renderPlotly({

    selected_var1 <- input$selected_var1
    selected_var1_dat <- df[[selected_var1]]

    selected_var2 <- input$selected_var2
    selected_var2_dat <- df[[selected_var2]]

    ggplot(data = df) + 
      geom_mosaic(aes(x = product(selected_var1_dat), 
                      fill = selected_var2_dat, na.rm = T))

  })
}

shinyApp(ui = ui, server = server) 

Which outputs this error message:

I've tried different ways to get around this problem with no luck. I've worked with Shiny quite a bit and it seems to work with every other ggplot graph I've used. Does anyone have any ideas on what might be going on?


Answer:

ggmosaic and plotly are not compatible currently. You can get your app to work without plotly with the following code.

library(shiny) 
library(tidyverse)
library(ggmosaic)
#library(plotly)

a <- "a"
b <- "b"
c <- "c"

df <- tribble(
  ~id, ~var1, ~var2, ~var3, 
  1, a, b, c,
  2, b, b, c,
  3, b, b, c,
  4, a, c, b, 
  5, a, a, a,
  6, b, c, c, 
  7, b, c, a,
  8, a, a, b,
  9, a, a, a, 
  10, b, b, c
)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "selected_var1",
                  label = "X:",
                  choices = names(df)[-1]),
      selectInput(inputId = "selected_var2",
                  label = "Y:", 
                  choices = names(df)[-1])
    ),
    mainPanel(
      plotOutput(outputId = "mosaic")
    )
  )
)

server <- function(input, output) {

  output$mosaic <- renderPlot({
    ggplot(data = df) + 
      geom_mosaic(aes(x = product(!!sym(input$selected_var1)), 
                      fill = !!sym(input$selected_var2)))
  })
}

shinyApp(ui = ui, server = server) 

Question:

library(ggmosaic) library(tidyverse)

I'm still attempting to learn some of the nuances of programming with standard evaluation. For this problem, I'm attempting to create a function using the "happy" dataset from ggmosaic to create a basic mosaic plot of the variables "health" and "happy".

Below is the code that I want to use to create a function using standard evaluation. I want to be able to enter any two categorical variables from the happy dataset and create a basic mosaic plot as outlined in the code.

happy%>%
na.omit()%>%
count(happy,health)%>%
ggplot()+
geom_mosaic(aes(weight=n,x=product(health),fill=health))

However, I can't quite get the code right. I've asked similar questions before, but I'm still struggling to understand when and where to use the .dots argument as well as how to specify the inputs in standard evaluation. Below is one of the incorrect versions of code I've been playing with...

Mosaic<-function(product="health",fill="happy"){
happy%>%na.omit()%>%
count_(c(product,fill))%>%
ggplot()+
geom_mosaic(aes_string(weight="n",x=product(product),fill=fill))
}

Any pointers to get this to work wouldbe be greatly appreciated, especially any advice on how to code this properly with SE.


Answer:

You could do:

Mosaic<-function(var_product="health",fill="happy"){
  happy%>%
    na.omit()%>%
    count_(c(var_product,fill))%>%
    ggplot(aes(weight=n))+
    geom_mosaic(aes_string(x=paste0("product(", var_product, ")"),fill=fill))
}

Example:

Mosaic("sex","degree")