Home > database >  Cut off geom_vline at geom_density height
Cut off geom_vline at geom_density height

Time:08-05

I am trying to highlight a specific point in a distribution. I am using geom_vline which works fine except that it extends beyond the curve drawn by geom_density. Is there any way to cut that vertical line off a the point it meets the curve drawn by geom_density?

library(ggplot2)

mtcars$car <- rownames(mtcars)

javelin <- mtcars[mtcars$car == "AMC Javelin", ]

ggplot(mtcars)  
  geom_density(aes(x = mpg))  
  geom_vline(data = javelin, aes(xintercept = mpg))

CodePudding user response:

You can't use geom_vline here. You'll have to calculate the correct point and use geom_segment, but this really isn't that complex:

ggplot(mtcars)  
  geom_density(aes(x = mpg))  
  geom_segment(data = as.data.frame(density(mtcars$mpg)[1:2]) %>%
                      filter(seq(nrow(.)) == which.min(abs(x - javelin$mpg))),
               aes(x, 0, xend = x, yend = y))

enter image description here

If you want this to be easily generalised, you can define a little helper function:

geom_vdensity <- function(data, at, ...) {
  ggplot2::geom_segment(
    data = dplyr::filter(as.data.frame(density(data)[1:2]),
                         seq_along(x) == which.min(abs(x - at))),
    ggplot2::aes(x, 0, xend = x, yend = y), ...)
}

This allows:

ggplot(mtcars)  
  geom_density(aes(x = mpg))  
  geom_vdensity(data = mtcars$mpg, at = javelin$mpg, color = "red")

enter image description here

and

ggplot(iris)  
  geom_density(aes(x = Petal.Length))  
  geom_vdensity(data = iris$Petal.Length, at = 4)

enter image description here

  • Related