3

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) 
mnist
  • 6,571
  • 1
  • 18
  • 41
fullera
  • 164
  • 6

3 Answers3

4

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])
StupidWolf
  • 45,075
  • 17
  • 40
  • 72
  • 1
    Thanks everyone, I found this option the easiest to implement. However I appreciate the angle of all other answers given which provide me new ways to approach these problems. – fullera May 23 '20 at 00:56
2

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)
  • 2
    Don't forget to use the data frame columns in the aes and in the label ('df$names', 'df$values', not the original vectors you defined) – Tomás Ribotta May 22 '20 at 23:34
2

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() 
mnist
  • 6,571
  • 1
  • 18
  • 41