what does ..level.. mean in ggplot::stat_density2d

2020-02-07 19:38发布

I've seen some examples when constructing a heatmap of having the fill variable set to ..level...

Such as in this example:

library(MASS)
ggplot(geyser, aes(x = duration, y = waiting)) + 
    geom_point() + 
    geom_density2d() + 
    stat_density2d(aes(fill = ..level..), geom = "polygon")

I suspect that the ..level.. means that the fill is set to the relative amount of layers present? Also could someone link me a good example of how to interpret these 2D-density plots, what does each contour represent etc.? I have searched online but couldn't find any suitable guide.

标签: r ggplot2
2条回答
对你真心纯属浪费
2楼-- · 2020-02-07 20:17

the stat_ functions compute new values and create new data frames. this one creates a data frame with a level variable. you can see it if you use ggplot_build vs plotting the graph:

library(ggplot2)
library(MASS)

gg <- ggplot(geyser, aes(x = duration, y = waiting)) + 
    geom_point() + 
    geom_density2d() + 
    stat_density2d(aes(fill = ..level..), geom = "polygon")

gb <- ggplot_build(gg)

head(gb$data[[3]])

##      fill level        x        y piece group PANEL
## 1 #132B43 0.002 3.876502 43.00000     1 1-001     1
## 2 #132B43 0.002 3.864478 43.09492     1 1-001     1
## 3 #132B43 0.002 3.817845 43.50833     1 1-001     1
## 4 #132B43 0.002 3.802885 43.65657     1 1-001     1
## 5 #132B43 0.002 3.771212 43.97583     1 1-001     1
## 6 #132B43 0.002 3.741335 44.31313     1 1-001     1

The ..level.. tells ggplot to reference that column in the newly build data frame.

Under the hood, ggplot is doing something similar to (this is not a replication of it 100% as it uses different plot limits, etc):

n <- 100
h <- c(bandwidth.nrd(geyser$duration), bandwidth.nrd(geyser$waiting))
dens <- kde2d(geyser$duration, geyser$waiting, n=n, h=h)
df <- data.frame(expand.grid(x = dens$x, y = dens$y), z = as.vector(dens$z))
head(df)

##           x  y            z
## 1 0.8333333 43 9.068691e-13
## 2 0.8799663 43 1.287684e-12
## 3 0.9265993 43 1.802768e-12
## 4 0.9732323 43 2.488479e-12
## 5 1.0198653 43 3.386816e-12
## 6 1.0664983 43 4.544811e-12

And also calling contourLines to get the polygons.

This is a decent introduction to the topic. Also look at ?kde2d in R help.

查看更多
SAY GOODBYE
3楼-- · 2020-02-07 20:19

Expanding on the answer provided by @hrbrmstr -- first, the call to geom_density2d() is redundant. That is, you can achieve the same results with:

library(ggplot2)
library(MASS)

gg <- ggplot(geyser, aes(x = duration, y = waiting)) + 
    geom_point() + 
    stat_density2d(aes(fill = ..level..), geom = "polygon")

Let's consider some other ways to visualize this density estimate that may help clarify what is going on:

base_plot <- ggplot(geyser, aes(x = duration, y = waiting)) + 
  geom_point()

base_plot + 
  stat_density2d(aes(color = ..level..))

Plot1

base_plot + 
  stat_density2d(aes(fill = ..density..), geom = "raster", contour = FALSE)

Plot2

base_plot +
  stat_density2d(aes(alpha = ..density..), geom = "tile", contour = FALSE)

Notice, however, we can no longer see the points generated from geom_point().

Plot3

Finally, note that you can control the bandwidth of the density estimate. To do this, we pass x and y bandwidth arguments to h (see ?kde2d):

base_plot +
  stat_density2d(aes(fill = ..density..), geom = "raster", contour = FALSE,
                 h = c(2, 5))

Plot4

Again, the points from geom_point() are hidden as they are behind the call to stat_density2d().

查看更多
登录 后发表回答