forcats icon indicating copy to clipboard operation
forcats copied to clipboard

Feature request: update fct_reorder to support horizontal bar plots with NA bars on the bottom

Open davidhodge931 opened this issue 4 years ago • 1 comments

It is not currently possible to easily make a horizontal bar graph where bars are ordered by size and with NA bars on the bottom of the graph.

The graph looks good vertically with NAs on the far right, but as soon as you flip the plot, the NAs are at the top, which in general is not good, given that you almost never want to emphasise the NA values.

A solution to this might be to update forcats::fct_reorder to have an argument to support this (e.g. na_flip = TRUE).

library(dplyr)
library(ggplot2)

plot_data <- iris %>% 
  group_by(Species) %>% 
  summarise(Petal.Length = mean(Petal.Length)) %>% 
  add_row(Species = "New species") %>% 
  mutate(Species = forcats::fct_reorder(Species, Petal.Length))

ggplot(plot_data) +
  geom_col(aes(Species, Petal.Length))

image

ggplot(plot_data) +
  geom_col(aes(Species, Petal.Length)) + 
  coord_flip()

image

davidhodge931 avatar Jul 08 '20 23:07 davidhodge931

A workaround...

library(dplyr)
library(ggplot2)

df <- tibble::tribble(
  ~region, ~year, ~data_value,
  "A", "2012", 3423,
  "A", "2017", 4423,
  "B", "2012", NA,
  "B", "2017", 2423,
  "C", "2012", NA,
  "C", "2017", NA)

all_na <- df %>% 
  group_by(region) %>% #if colouring
  summarise(all_na = all(is.na(data_value))) %>% 
  filter(all_na == TRUE) %>% 
  pull(region)

df <- df %>% 
  mutate(region = forcats::fct_reorder(region, data_value, .fun = median, na.rm = TRUE))  

levels(df$region)

ggplot(df) +
  geom_col(aes(x = region, y = data_value, fill = year), position = "dodge") +
  coord_flip()

df <- df %>% 
  mutate(region = forcats::fct_relevel(region, all_na))  

levels(df$region)

ggplot(df) +
  geom_col(aes(x = region, y = data_value, fill = year), position = "dodge") +
  coord_flip()

davidhodge931 avatar Sep 29 '20 22:09 davidhodge931

I think fct_order() could gain a na_last argument to match order().

hadley avatar Jan 03 '23 15:01 hadley