Skip to content

position_jitterdodge() failed when attribute fill is not specified #3656

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
qxxxd opened this issue Dec 5, 2019 · 7 comments · Fixed by #5922
Closed

position_jitterdodge() failed when attribute fill is not specified #3656

qxxxd opened this issue Dec 5, 2019 · 7 comments · Fixed by #5922
Labels
bug an unexpected problem or unintended behavior positions 🥇

Comments

@qxxxd
Copy link

qxxxd commented Dec 5, 2019

Hello,

I was trying to produce a scatter plot with points labelled by the variable text and dodged by the color variable group. The position_dodge() function worked fine, as shown in the 1st figure below. But when I tried to jitter the points using position_jitterdodge(), this function would fail unless I added the fill attribute in the aes(). The desired output is shown in the 2nd figure below.

The version of ggplot2 is 3.2.1.

I'm not sure if this is a bug or intended?

Thank you for any help.

library(ggplot2)
# pseudo data
set.seed(123)
d <- data.frame(x = rep(as.character(1:3), each = 4),
                y = rnorm(12),
                group = rep(as.character(1:2), 6),
                text = rep(LETTERS[1:4], 3))

# using position_jitter()
pos <- position_jitter(width = 0.2, 
                   seed = 10)
ggplot(d, aes(x= x, y = y,
              color = group,
              label = text)) +
  geom_point(position = pos, size = 5) + 
  geom_text(position = pos, size = 4, color = "white")

# using position_jitterdodge() WITHOUT `fill` attribute
pos <- position_jitterdodge(jitter.width = 0.2,
                            dodge.width = 0.5,
                            seed = 10)
ggplot(d, aes(x= x, y = y,
              color = group,
              label = text)) +
  geom_point(position = pos, size = 5) + 
  geom_text(position = pos, size = 4, color = "white")

#> Error: position_jitterdodge() requires at least one aesthetic to dodge by

# using position_jitterdodge() WITH `fill` attribute
ggplot(d, aes(x= x, y = y,
              fill = group,
              color = group,
              label = text)) +
  geom_point(position = pos, size = 5) + 
  geom_text(position = pos, size = 4, color = "white")

Created on 2019-12-04 by the reprex package (v0.3.0)

@clauswilke
Copy link
Member

Likely related to #3612, though it's surprising that setting the color aesthetic is not sufficient here.

@clauswilke
Copy link
Member

clauswilke commented Dec 5, 2019

This seems to be happening specifically because color is set manually in geom_text(). However, surprisingly, setting a group aesthetic does not fix things here (unlike in #3612).

library(ggplot2)

# pseudo data
set.seed(123)
d <- data.frame(x = rep(as.character(1:3), each = 4),
                y = rnorm(12),
                group = rep(as.character(1:2), 6),
                text = rep(LETTERS[1:4], 3))

pos <- position_jitterdodge(jitter.width = 0.2,
                            dodge.width = 0.5,
                            seed = 10)

# works
ggplot(d, aes(x= x, y = y,
              color = group,
              label = text)) +
  geom_text(position = pos, size = 4)

# doesn't work, color is set explicitly
ggplot(d, aes(x= x, y = y,
              color = group,
              label = text)) +
  geom_text(position = pos, size = 4, color = "black")
#> Error: `position_jitterdodge()` requires at least one aesthetic to dodge by
# works
ggplot(d, aes(x= x, y = y,
              color = group,
              fill = group,
              label = text)) +
  geom_text(position = pos, size = 4, color = "black")

# doesn't work
ggplot(d, aes(x= x, y = y,
              color = group,
              group = group,
              label = text)) +
  geom_text(position = pos, size = 4, color = "black")
#> Error: `position_jitterdodge()` requires at least one aesthetic to dodge by

Created on 2019-12-04 by the reprex package (v0.3.0)

@thomasp85 thomasp85 added bug an unexpected problem or unintended behavior positions 🥇 labels Jan 21, 2020
@thomasp85 thomasp85 added this to the ggplot2 3.3.4 milestone Mar 25, 2021
@thomasp85
Copy link
Member

@karawoo do you have any knowledge about this logic?

dodgecols <- intersect(c("fill", "colour", "linetype", "shape", "size", "alpha"), colnames(data))
if (length(dodgecols) == 0) {
abort("`position_jitterdodge()` requires at least one aesthetic to dodge by")
}
ndodge <- lapply(data[dodgecols], levels) # returns NULL for numeric, i.e. non-dodge layers
ndodge <- length(unique(unlist(ndodge)))

Why is group ignored here? Sorry if this not your table but you are the "dodge-master" in my head 🙂

@karawoo
Copy link
Member

karawoo commented Apr 20, 2021

I haven't touched jitterdodge so I don't really know, but looking at it I can't see any reason why "group" should not be included.

@thomasp85
Copy link
Member

The only thing I can see is that group will be derived from the other aesthetics if not given explicitly which may lead to some sort of compounding in the two next calls...

I'll try to experiment with it and see if it have any negative consequences

@teunbrand
Copy link
Collaborator

I think the data should only be dodged by group, not any of the other variables.
That'd allow flexibility on how the points are displayed by overriding the default grouping.
In addition, if we only have 1 x variable, the jitter is probably too much.

library(ggplot2)
p <- ggplot(mpg, aes("x", displ)) +
  geom_point(position = position_jitterdodge())

# Throws error
p
#> Error in `geom_point()`:
#> ! Problem while computing position.
#> ℹ Error occurred in the 1st layer.
#> Caused by error in `setup_params()`:
#> ! `position_jitterdodge()` requires at least one aesthetic to dodge by

# Too much jitter.width?
p + aes(colour = drv)

# Throws error
p + aes(group = drv)
#> Error in `geom_point()`:
#> ! Problem while computing position.
#> ℹ Error occurred in the 1st layer.
#> Caused by error in `setup_params()`:
#> ! `position_jitterdodge()` requires at least one aesthetic to dodge by

Created on 2024-05-31 with reprex v2.1.0

@teunbrand
Copy link
Collaborator

Also, if you use a string, e.g. position = "jitterdodge" it fails with an error:

library(ggplot2)

# What it should do
ggplot(mpg, aes(factor(cyl), displ, colour = factor(year))) +
  geom_point(position = position_jitterdodge())

ggplot(mpg, aes(factor(cyl), displ, colour = factor(year))) +
  geom_point(position = "jitterdodge")
#> Error in `geom_point()`:
#> ! Problem while computing position.
#> ℹ Error occurred in the 1st layer.
#> Caused by error in `if (params$jitter.height > 0) ...`:
#> ! argument is of length zero

Created on 2024-05-31 with reprex v2.1.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug an unexpected problem or unintended behavior positions 🥇
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants