Daniel Valencia C.
Daniel Valencia C.

Reputation: 2279

How to show empty levels in faceted plots?

I have a data frame that contains information classified by 2 factors, factor “a” and factor “b”. Factor “a” has levels A, B and C and factor “b” has levels R, S, T, U and V.

a <- c("A", "A", "A", "A", "B", "B", "B", "B")
b <- c("R", "R", "R", "S", "T", "T", "U", "U")
c <- 1:8

DF <- data.frame(a,b,c)

In the data table above, you can see that level C (for factor “a”) and level V (for factor “b”) have no information.

How can I create a facet for level C that shows the count of 0 for level V in a bar chart separated by facets?

library(ggplot2)

ggplot(data = DF,
       aes(x = b)) +
  geom_bar() +
  geom_text(aes(label=after_stat(count)),
            stat = "count") +
  facet_grid(~ a,
             space = "free",
             scales = "free")

enter image description here

Upvotes: 2

Views: 58

Answers (2)

Eric Hunt
Eric Hunt

Reputation: 171

I just wanted to add onto what @stefan wrote above, as this is interesting and I've run into something similar before – highlighting the advantage of aggregation before plotting. If your levels are defined in the factor explicitly – i.e. not just through their existence in the data when calling factor(), you can use tidyr::complete() to create the missing combinations.

df <- data.frame(
  a = factor(
    c("A", "A", "A", "A", "B", "B", "B", "B"),
    levels = c("A", "B", "C")
  ),
  b = factor(
    c("R", "R", "R", "S", "T", "T", "U", "U"),
    levels = c("R", "S", "T", "U", "V")
  ),
  c = 1:8
) |>
  tidyr::complete(a, b) |>
  dplyr::mutate(count = sum(!is.na(c)), .by = c(a, b))

df
#> # A tibble: 19 × 4
#>    a     b         c count
#>    <fct> <fct> <int> <int>
#>  1 A     R         1     3
#>  2 A     R         2     3
#>  3 A     R         3     3
#>  4 A     S         4     1
#>  5 A     T        NA     0
#>  6 A     U        NA     0
#>  7 A     V        NA     0
#>  8 B     R        NA     0
#>  9 B     S        NA     0
#> 10 B     T         5     2
#> 11 B     T         6     2
#> 12 B     U         7     2
#> 13 B     U         8     2
#> 14 B     V        NA     0
#> 15 C     R        NA     0
#> 16 C     S        NA     0
#> 17 C     T        NA     0
#> 18 C     U        NA     0
#> 19 C     V        NA     0

ggplot2::ggplot(df, ggplot2::aes(x = b, y = count)) +
ggplot2::geom_col() +
ggplot2::geom_text(ggplot2::aes(label = count)) +
ggplot2::facet_grid(cols = ggplot2::vars(a))

Created on 2024-10-08 with reprex v2.1.1.9000

Upvotes: 1

stefan
stefan

Reputation: 124093

IMHO the easiest option would be to aggregate your data outside of ggplot then add an additional row for the C-V combo with a count of 0:

library(ggplot2)
library(dplyr, warn = FALSE)

DF <- DF |>
  dplyr::count(a, b) |>
  dplyr::add_row(a = "C", b = "V", n = 0)

ggplot(
  data = DF,
  aes(x = b, y = n)
) +
  geom_col() +
  geom_text(
    aes(
      label = n
    )
  ) +
  facet_grid(~a,
    space = "free",
    scales = "free"
  )

Upvotes: 2

Related Questions