Why is bins parameter unknown for the stat_density2d function? (ggmap)
Asked Answered
D

2

1

I have been stuck with this for hours. When I run this :

library(ggmap)
set.seed(1)
n=100

df <- data.frame(x=rnorm(n, 0, 1), y=rnorm(n, 0, 1))

TestData <- ggplot (data = df) +
  stat_density2d(aes(x = x, y = y,fill = as.factor(..level..)),bins=4, geom = "polygon",) +
  geom_point(aes(x = x, y = y)) +
  scale_fill_manual(values = c("yellow","red","green","royalblue", "black"))

I get this error message :

Error: Unknown parameters: bins

Does anyone know why?

Decapod answered 22/12, 2015 at 7:58 Comment(6)
Why do you think there is a bins argument inside stat_density2d? It is not described in the help page.Tenon
It is not such a bad question. The OP should have posted this link though: #19329818 since the code was copied from there.Cordelier
Clearly the bins parameter has been removed, you can use the n parameter instead to change the contouring a bit, but I haven't seen how to directly control the number of levels generated. There probably is a way, but I need to research it more.Cordelier
Someone who knows more about this function will undoubtedly enlighten us soon. Read the last post in the above link for the most information.Cordelier
I don't think stat_density2d ever had a bins parameter. I checked version 0.8.6 (from 2010) and it was not there then. Version 2.0.0 is just more strict regarding accepting unexpected parameters.Asberry
It did not have a documented parameter per-se. But it had a parameter that was passed through to MASS:kde2d. Read the link I posted in the 2nd comment above for more information (and an example). And in a similar way you can still use the parameters n or h which is not documented. Try it.Cordelier
C
4

Okay, adding this one as a second answer because I think the descriptions and comments in the first answer are useful and I don't feel like merging them. Basically I figured there must be an easy way to restore the regressed functionality. And after awhile, and learning some basics about ggplot2, I got this to work by overriding some ggplot2 functions:

library(ggmap)
library(ggplot2)

# -------------------------------
# start copy from stat-density-2d.R

stat_density_2d <- function(mapping = NULL, data = NULL, geom = "density_2d",
                            position = "identity", contour = TRUE,
                            n = 100, h = NULL, na.rm = FALSE,bins=0,
                            show.legend = NA, inherit.aes = TRUE, ...) {
  layer(
    data = data,
    mapping = mapping,
    stat = StatDensity2d,
    geom = geom,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      na.rm = na.rm,
      contour = contour,
      n = n,
      bins=bins,
      ...
    )
  )
}

stat_density2d <- stat_density_2d

StatDensity2d <- 
  ggproto("StatDensity2d", Stat,
          default_aes = aes(colour = "#3366FF", size = 0.5),

          required_aes = c("x", "y"),

          compute_group = function(data, scales, na.rm = FALSE, h = NULL,
                                   contour = TRUE, n = 100,bins=0) {
            if (is.null(h)) {
              h <- c(MASS::bandwidth.nrd(data$x), MASS::bandwidth.nrd(data$y))
            }

            dens <- MASS::kde2d(
              data$x, data$y, h = h, n = n,
              lims = c(scales$x$dimension(), scales$y$dimension())
            )
            df <- data.frame(expand.grid(x = dens$x, y = dens$y), z = as.vector(dens$z))
            df$group <- data$group[1]

            if (contour) {
              #  StatContour$compute_panel(df, scales,bins=bins,...) # bad dots...
              if (bins>0){
                StatContour$compute_panel(df, scales,bins)
              } else {
                StatContour$compute_panel(df, scales)
              }
            } else {
              names(df) <- c("x", "y", "density", "group")
              df$level <- 1
              df$piece <- 1
              df
            }
          }
  )

# end copy from stat-density-2d.R
# -------------------------------

set.seed(1)
n=100

df <- data.frame(x=rnorm(n, 0, 1), y=rnorm(n, 0, 1))

TestData <- ggplot (data = df) +
  stat_density2d(aes(x = x, y = y,fill = as.factor(..level..)),bins=5,geom = "polygon") +
  geom_point(aes(x = x, y = y)) +
  scale_fill_manual(values = c("yellow","red","green","royalblue", "black"))
print(TestData)

Which yields the result. Note that varying the bins parameter has the desired effect now, which cannot be replicated by varying the n parameter.

enter image description here

Cordelier answered 29/12, 2015 at 14:56 Comment(1)
I just got a notice that this has been fixed in the github version of ggplot2, and the bug was closed by hadley.Cordelier
C
0

update:

After an extended discussion with Roland (see the comments), he determined it is probably a regression bug and filed a bug report.


As the question is "why is the bins parameter unknown?", and I spent a fair amount of time researching it, I will answer it.

Your example obviously comes from this link from Oct 2013, where the parameter is used. How to correctly interpret ggplot's stat_density2d

However it was never a documented parameter, and it is not clear that it is being used there. It is probably a parameter that is being passed through to other libraries (like MASS) that are being used by stat_density2d.

We can get the code to work by getting rid of the scale_fill_manual call and using this:

library(ggmap)
set.seed(1)
n=100

df <- data.frame(x=rnorm(n, 0, 1), y=rnorm(n, 0, 1))

TestData <- ggplot (data = df) +
  stat_density2d(aes(x = x, y = y,fill = as.factor(..level..)), geom = "polygon",) +
  geom_point(aes(x = x, y = y)) 
#  scale_fill_manual(values = c("yellow","red","green","royalblue", "black"))
print(TestData)

which yields this: enter image description here

Since this looks rather different from the plot posted in the original Oct 2013 link, I would say that stat_density2d has been extensively rewritten since then, or maybe MASS:kde2d (or another MASS routine), and that the bin parameter is no longer accepted. It is also not clear that that parameter ever did anything (read the link).

You can however vary the parameters n and h - also undocumented from the stat_density2d point-of-view (as far as I can tell).

Cordelier answered 22/12, 2015 at 13:7 Comment(11)
MASS::kde2d doesn't have a bins parameter.Asberry
Maybe it used to. Clearly something else did. Did you read the post this originated from? They go over it in some detail there.Cordelier
I don't think so. See the second answer there.Asberry
The post from Bryan Hanson? He talks about bins. He doesn't understand what it does, or how it is used, but it clearly was a parameter that the function accepted. What is your point?Cordelier
Also take a careful look at the first two plots. The first one has bins=4 and has 4 colored buckets of values. The second one has bins=5, and has 5 colored buckets. So that is what bins did apparently. And that functionality is now gone... And the OP here got hung up on that, because that is what he wanted to control.Cordelier
I checked. kde2d didn't have a bins parameter even back in 2009. stat_density2d didn't have one then either. You could check further back (the old versions are archivated on CRAN), but I don't think it ever had any effect. The OP of the linked questions even confirms that.Asberry
Then it was some other function that stat_density2d used. How else do you explain the appearance of the original post from 2013? We could chat about it if you want. I live in Germany so we are probably in the same timezone.Cordelier
OK, I had a closer look. The bins parameter was actually passed to stat_contour. Since the ellipses from stat_density are no longer passed to stat_contour, it is no longer possible to specify the number of bins. This seems like a regression. I'll file a bug report.Asberry
Yeah, I just found this. It is a very useful feature. github.com/trinker/embodied/blob/master/inst/example_plots/…Cordelier
I think hans glick deserves an upvote for his suffering. I gave him one, but it only got him to 0.Cordelier
Sorry, but he won't get one from me unless he adds his sessionInfo() to the question.Asberry

© 2022 - 2024 — McMap. All rights reserved.