How to drop x value from ggplot with discrete axis?

Viewed 344

This may be something that is an easy fix.

I am creating a new dashboard in shiny and it's been asked by my company that all plots be ordered by a list. So naturally I created a list and used scale_x_discrete(limits = list). However, what is being asked for now is for values where it is equal to zero to be removed whilst still retaining the order of the list. Is this possible to do with scale_x_discrete()?

i.e the plot generated would exclude the variable "different" whilst keeping the order of names <- c("before", "same", "different").

Any help is greatly appreciated, here is a reproducible example below.

# packages ----------------------------------------------------------------
{
  library(dplyr)
  library(ggplot2)
}
# Data --------------------------------------------------------------------

names <- c("before", "same", "different")
values <- c(7, 90, 0)

df <- data.frame(names, values)


# ggplot ------------------------------------------------------------------

ggplot(df, aes(names, values))+
  geom_bar(stat = "identity")+
  scale_x_discrete(limits = names) 
3 Answers

You just subset the names when you pass in the limits:

ggplot(df, aes(names, values))+
  geom_bar(stat = "identity")+
  scale_x_discrete(limits = names[values>0])

You can program a for loop that removes the rows of the data frame that you actually don't wanna show in your plot.

# packages ----------------------------------------------------------------
{
  library(dplyr)
  library(ggplot2)
}
# Data --------------------------------------------------------------------

names <- c("before", "same", "different")
values <- c(7, 90, 0)

df <- data.frame(names, values)

#Remove empty categories
for(i in 1:length(values))
{
      if(values[i] == 0)
      {
      df <- df[-c(i),]
      }
}

# ggplot ------------------------------------------------------------------

ggplot(df, aes(df$names, df$values))+
geom_bar(stat = "identity")+
scale_x_discrete(limits = df$names)

Well sure you can acheive this by preparing your data and vectors beforehand but what you should do in such situations: use ordered factors:

# ggplot ------------------------------------------------------------------
relevant_df <- df %>% 
  filter(values != 0) 

relevant_df %>% 
  ggplot(aes(names, values)) +
  geom_bar(stat = "identity") +
  scale_x_discrete(limits = relevant_df$names) 

# with ordered factor ----------------------------------------------------------
df %>% 
  # little bit of confusion here with vector and variable name
  # but just define your desired order in the second argument
  mutate(names = ordered(names, names)) %>% 
  filter(values != 0) %>% 
  ggplot(aes(names, values)) +
  geom_bar(stat = "identity") +
  scale_x_discrete() 
Related