How to plot a contour line showing where 95% of values fall within, in R and in ggplot2

前端 未结 5 1563
长情又很酷
长情又很酷 2020-12-05 15:21

Say we have:

x <- rnorm(1000)
y <- rnorm(1000)

How do I use ggplot2 to produce a plot containing the two following geoms:

    <
5条回答
  •  时光说笑
    2020-12-05 16:24

    Just mixing answers from above, putting them in a more tidyverse friendly way, and allowing for multiple contour levels. I use here geom_path(group=probs), adding them manually geom_text. Another approach is to use geom_path(colour=probs) which will automatically label the contours as legend.

    library(ks)
    library(tidyverse)
    
    set.seed(1001)
    
    ## data
    d <- MASS::mvrnorm(1000, c(0, 0.2), matrix(c(1, 0.4, 1, 0.4), ncol=2)) %>% 
      magrittr::set_colnames(c("x", "y")) %>% 
      as_tibble() 
    
    ## density function
    kd <- ks::kde(d, compute.cont=TRUE, h=0.2)
    
    ## extract results
    get_contour <- function(kd_out=kd, prob="5%") {
      contour_95 <- with(kd_out, contourLines(x=eval.points[[1]], y=eval.points[[2]],
                                          z=estimate, levels=cont[prob])[[1]])
      as_tibble(contour_95) %>% 
        mutate(prob = prob)
    }
    
    dat_out <- map_dfr(c("10%", "20%","80%", "90%"), ~get_contour(kd, .)) %>% 
      group_by(prob) %>% 
      mutate(n_val = 1:n()) %>% 
      ungroup()
    
    ## clean kde output
    kd_df <- expand_grid(x=kd$eval.points[[1]], y=kd$eval.points[[2]]) %>% 
      mutate(z = c(kd$estimate %>% t))
    
    ggplot(data=kd_df, aes(x, y)) +
      geom_tile(aes(fill=z)) +
      geom_point(data = d, alpha = I(0.4), size = I(0.4), colour = I("yellow")) +
      geom_path(aes(x, y, group = prob), 
                data=filter(dat_out, !n_val %in% 1:3), colour = I("white")) +
      geom_text(aes(label = prob), data = 
                  filter(dat_out, (prob%in% c("10%", "20%","80%") & n_val==1) | (prob%in% c("90%") & n_val==20)),
                colour = I("black"), size =I(3))+
      scale_fill_viridis_c()+
      theme_bw() +
      theme(legend.position = "none")
    

    Created on 2019-06-25 by the reprex package (v0.3.0)

提交回复
热议问题