PDA
PDA

Reputation: 11

geom_text fails with empty tibble (sometimes)

After creating a figure, I want to label some points. The labeled points are the result of a filtering process, and may sometimes be empty. I want geom_text to fail gracefully when there are no points to label, (i.e., do nothing). The problem is that rather than failing gracefully, R gives me an error. The error seems entirely dependent on whether I specify hjust in the aesthetic.

This works (in the sense that it does nothing):

library(ggplot2)
library(tidyverse)


ggplot() +
  geom_text(
    data = tibble(x = numeric(),
                  y = numeric(),
                  z = integer()),
    mapping = aes(x = x,
                  y = y,
                  label = z)
  )

Created on 2020-07-23 by the reprex package (v0.3.0)

This does not:

library(ggplot2)
library(tidyverse)

ggplot() +
  geom_text(
    data = tibble(x = numeric(),
                  y = numeric(),
                  z = integer()),
    mapping = aes(
      x = x,
      y = y,
      label = z,
      hjust = 0
    )
  )
#> Error: Aesthetics must be either length 1 or the same as the data (1): x, y and label

Created on 2020-07-23 by the reprex package (v0.3.0)

Given that I don't know in advance whether the set of points to be labeled will be empty, how can I specify hjust?

Upvotes: 1

Views: 178

Answers (2)

Axeman
Axeman

Reputation: 35242

All things mapped inside aes should be the same length. numeric() is of zero length, but 0 is of length 1. If aes does not vary depending on the data, set hjust instead of mapping it using aes.

ggplot() +
  geom_text(
    data = tibble(x = numeric(),
                  y = numeric(),
                  z = integer()),
    mapping = aes(x = x,
                  y = y,
                  label = z),
    hjust = 0)
  )

Note that I think it should be possible to include hjust = 0, since arguments of length 1 are supposed to be exempt from the equal length restriction, but apparently this does not work with datasets with 0 observations. This might be considered a bug (at least the error message makes little sense in this case). Regardless, there is no need here to include hjust inside aes in the first place, and I would always write it as the code above illustrates.

Upvotes: 2

Rui Barradas
Rui Barradas

Reputation: 76402

This is not very pretty but it seems to work. No promises, though.

Works with zero length data.

ggplot() +
  geom_text(
    data = tibble(x = numeric(),
                  y = numeric(),
                  z = integer()),
    mapping = aes(
      x = x,
      y = y,
      label = z,
      hjust = numeric(if(length(x)) 1 else 0)
    )
  )

And works with data of length greater than zero.

ggplot() +
  geom_text(
    data = tibble(x = numeric(1),
                  y = numeric(1),
                  z = integer(1)),
    mapping = aes(
      x = x,
      y = y,
      label = z,
      hjust = numeric(if(length(x)) 1 else 0)
    )
  )

Upvotes: 0

Related Questions