Skip to content
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

stat_function() doesn't work without dummy data #3983

Closed
clauswilke opened this issue May 2, 2020 · 3 comments · Fixed by #3984
Closed

stat_function() doesn't work without dummy data #3983

clauswilke opened this issue May 2, 2020 · 3 comments · Fixed by #3984

Comments

@clauswilke
Copy link
Member

clauswilke commented May 2, 2020

I would have expected the second and third example below to work, but it doesn't.

library(ggplot2)

# works
ggplot(data.frame(x = c(-5, 5)), aes(x)) + 
  stat_function(fun = dnorm)

# doesn't work
ggplot() + xlim(-5, 5) + 
  stat_function(fun = dnorm)

# doesn't work
ggplot() + 
  stat_function(fun = dnorm, xlim = c(-5, 5))

Created on 2020-05-01 by the reprex package (v0.3.0)

The problem seems to be that stat_function() doesn't return any data in the second and third case, or the data gets somehow deleted. It would be nice if we could solve this before the 3.3.1 release, I assume (hope!) it's a simple fix.

library(ggplot2)

p <- ggplot(data.frame(x = c(-5, 5)), aes(x)) + 
  stat_function(fun = dnorm)
head(layer_data(p))
#>      x            y PANEL group colour size linetype alpha
#> 1 -5.0 1.486720e-06     1    -1  black  0.5        1    NA
#> 2 -4.9 2.438961e-06     1    -1  black  0.5        1    NA
#> 3 -4.8 3.961299e-06     1    -1  black  0.5        1    NA
#> 4 -4.7 6.369825e-06     1    -1  black  0.5        1    NA
#> 5 -4.6 1.014085e-05     1    -1  black  0.5        1    NA
#> 6 -4.5 1.598374e-05     1    -1  black  0.5        1    NA

p <- ggplot() + xlim(-5, 5) + 
  stat_function(fun = dnorm)
layer_data(p)
#> data frame with 0 columns and 0 rows

p <- ggplot() + 
  stat_function(fun = dnorm, xlim = c(-5, 5))
layer_data(p)
#> data frame with 0 columns and 0 rows

Created on 2020-05-01 by the reprex package (v0.3.0)

@clauswilke
Copy link
Member Author

clauswilke commented May 2, 2020

We can work around this issue by adding at least one group explicitly.

library(ggplot2)

# doesn't work
ggplot() + xlim(-5, 5) +
  stat_function(fun = dnorm)

# works
ggplot() + xlim(-5, 5) +
  stat_function(aes(group = 1), fun = dnorm)

Created on 2020-05-01 by the reprex package (v0.3.0)

@thomasp85 Can you see a way to simulate this via setup_data() or default_aes or required_aes? I couldn't get any of these approaches to work. I could reimplement compute_panel() and ignore the check for an empty data frame, but I'd rather not do that.

@clauswilke
Copy link
Member Author

clauswilke commented May 2, 2020

The reason why setup_data() doesn't work is it isn't even called if the input data is empty:

ggplot2/R/layer.r

Lines 271 to 278 in 49aca36

compute_statistic = function(self, data, layout) {
if (empty(data))
return(new_data_frame())
params <- self$stat$setup_params(data, self$stat_params)
data <- self$stat$setup_data(data, params)
self$stat$compute_layer(data, params, layout)
},

For the same reason, overriding compute_panel() won't do anything.

@clauswilke
Copy link
Member Author

clauswilke commented May 2, 2020

Never mind, I figured it out. PR #3984.

library(ggplot2)

ggplot() + xlim(-5, 5) + 
  geom_function(fun = dnorm)

ggplot() + xlim(-5, 5) + 
  geom_function(fun = dnorm) + 
  scale_y_log10()

ggplot() + 
  geom_function(fun = dnorm, xlim = c(-5, 5))

ggplot() + 
  geom_function(fun = dnorm)

Created on 2020-05-02 by the reprex package (v0.3.0)

And everything else I've fixed previously still works.

library(tidyverse)

data <- tibble(
  x = 1:50,
  y = x*x - 2*x + 500 + 200*rnorm(50),
  a = sample(letters[1:3], 50, replace = TRUE)
)

ggplot(data, aes(x, y)) +
  geom_point(aes(color = "data")) +
  geom_function(aes(color = "function"), fun = ~.x*.x - 2*.x + 500) +
  scale_y_log10() + scale_x_log10()

ggplot(data, aes(x, y, color = a)) +
  geom_point() +
  geom_function(fun = ~.x*.x - 2*.x + 500) +
  scale_y_log10() + facet_wrap(~a)

Created on 2020-05-02 by the reprex package (v0.3.0)

@clauswilke clauswilke added this to the ggplot2 3.3.1 milestone May 2, 2020
clauswilke added a commit that referenced this issue May 15, 2020
* make stat_function() work with empty input data. fixes #3983.

* update news item, fix documentation, add unit tests

* one more test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant