【问题标题】:plot a circle/convex hull arround a given percentage of points围绕给定百分比的点绘制圆形/凸包
【发布时间】:2015-07-29 20:00:59
【问题描述】:

我有

x=rnorm(100)
y=rnorm(100)
plot(x,y)
abline(h=0); abline(v=0)

从点(0,0) 向外,我想画一个轮廓/圆/椭圆/徒手凸包,它包含任何给定百分比的点。

是否有任何功能或包可以自动执行此操作?到目前为止,我已经尝试了以下方法,但我只能通过一些外推和近似得到一个圆。

到目前为止我已经尝试过了:

#calculate radius
r<- sqrt(x^2+y^2)

df<-data.frame(radius=seq(0,3,0.1), percentage=NA)

#get the percentage of points that have a smaller radius than i
k<-1
for (i in seq(0,3,0.1)){
  df$percentage[k] <- sum(r<i)/length(r)
  k<-k+1
}

#extrapolation function
prox.function<- approxfun(df$percentage, df$radius)


#get the radius of the circle that encloses about 50% of
prox.function(.50)

#draw the circle
library(plotrix)
draw.circle(0,0,prox.function(.50))

【问题讨论】:

    标签: r plot convex-hull ggproto


    【解决方案1】:

    包围分数 f 点的半径是:

    f <- 0.5 # use half for this example as in the question
    sort(r)[ ceiling(f * length(r)) ]
    

    【讨论】:

      【解决方案2】:

      是的,我们可以为 ggplot 创建一个新的几何图形,它将围绕数据中所有点的任何给定百分比绘制一个凸包。这类似于bagplot,并使用了aplpack 包中bagplot 函数的一些代码(固定为50% 的点)。

      这是新几何图形的定义,允许您选择要包围的点百分比:

      library(ggplot2)
      
      # Here's the stat_
      StatBag <- ggproto("Statbag", Stat,
                         compute_group = function(data, scales, prop = 0.5) {
      
                           #################################
                           #################################
                           # originally from aplpack package, plotting functions removed
                           plothulls_ <- function(x, y, fraction, n.hull = 1,
                                                  col.hull, lty.hull, lwd.hull, density=0, ...){
                             # function for data peeling:
                             # x,y : data
                             # fraction.in.inner.hull : max percentage of points within the hull to be drawn
                             # n.hull : number of hulls to be plotted (if there is no fractiion argument)
                             # col.hull, lty.hull, lwd.hull : style of hull line
                             # plotting bits have been removed, BM 160321
                             # pw 130524
                             if(ncol(x) == 2){ y <- x[,2]; x <- x[,1] }
                             n <- length(x)
                             if(!missing(fraction)) { # find special hull
                               n.hull <- 1
                               if(missing(col.hull)) col.hull <- 1
                               if(missing(lty.hull)) lty.hull <- 1
                               if(missing(lwd.hull)) lwd.hull <- 1
                               x.old <- x; y.old <- y
                               idx <- chull(x,y); x.hull <- x[idx]; y.hull <- y[idx]
                               for( i in 1:(length(x)/3)){
                                 x <- x[-idx]; y <- y[-idx]
                                 if( (length(x)/n) < fraction ){
                                   return(cbind(x.hull,y.hull))
                                 }
                                 idx <- chull(x,y); x.hull <- x[idx]; y.hull <- y[idx];
                               }
                             }
                             if(missing(col.hull)) col.hull <- 1:n.hull
                             if(length(col.hull)) col.hull <- rep(col.hull,n.hull)
                             if(missing(lty.hull)) lty.hull <- 1:n.hull
                             if(length(lty.hull)) lty.hull <- rep(lty.hull,n.hull)
                             if(missing(lwd.hull)) lwd.hull <- 1
                             if(length(lwd.hull)) lwd.hull <- rep(lwd.hull,n.hull)
                             result <- NULL
                             for( i in 1:n.hull){
                               idx <- chull(x,y); x.hull <- x[idx]; y.hull <- y[idx]
                               result <- c(result, list( cbind(x.hull,y.hull) ))
                               x <- x[-idx]; y <- y[-idx]
                               if(0 == length(x)) return(result)
                             }
                             result
                           } # end of definition of plothulls
                           #################################
      
      
                           # prepare data to go into function below
                           the_matrix <- matrix(data = c(data$x, data$y), ncol = 2)
      
                           # get data out of function as df with names
                           setNames(data.frame(plothulls_(the_matrix, fraction = prop)), nm = c("x", "y"))
                           # how can we get the hull and loop vertices passed on also?
                         },
      
                         required_aes = c("x", "y")
      )
      
      # Here's the stat_ function
      #' @inheritParams ggplot2::stat_identity
      #' @param prop Proportion of all the points to be included in the bag (default is 0.5)
      stat_bag <- function(mapping = NULL, data = NULL, geom = "polygon",
                           position = "identity", na.rm = FALSE, show.legend = NA, 
                           inherit.aes = TRUE, prop = 0.5, alpha = 0.3, ...) {
        layer(
          stat = StatBag, data = data, mapping = mapping, geom = geom, 
          position = position, show.legend = show.legend, inherit.aes = inherit.aes,
          params = list(na.rm = na.rm, prop = prop, alpha = alpha, ...)
        )
      }
      
      # here's the geom_
      geom_bag <- function(mapping = NULL, data = NULL,
                           stat = "identity", position = "identity",
                           prop = 0.5, 
                           alpha = 0.3,
                           ...,
                           na.rm = FALSE,
                           show.legend = NA,
                           inherit.aes = TRUE) {
        layer(
          data = data,
          mapping = mapping,
          stat = StatBag,
          geom = GeomBag,
          position = position,
          show.legend = show.legend,
          inherit.aes = inherit.aes,
          params = list(
            na.rm = na.rm,
            alpha = alpha,
            prop = prop,
            ...
          )
        )
      }
      
      #' @rdname ggplot2-ggproto
      #' @format NULL
      #' @usage NULL
      #' @export
      GeomBag <- ggproto("GeomBag", Geom,
                         draw_group = function(data, panel_scales, coord) {
                           n <- nrow(data)
                           if (n == 1) return(zeroGrob())
      
                           munched <- coord_munch(coord, data, panel_scales)
                           # Sort by group to make sure that colors, fill, etc. come in same order
                           munched <- munched[order(munched$group), ]
      
                           # For gpar(), there is one entry per polygon (not one entry per point).
                           # We'll pull the first value from each group, and assume all these values
                           # are the same within each group.
                           first_idx <- !duplicated(munched$group)
                           first_rows <- munched[first_idx, ]
      
                           ggplot2:::ggname("geom_bag",
                                            grid:::polygonGrob(munched$x, munched$y, default.units = "native",
                                                               id = munched$group,
                                                               gp = grid::gpar(
                                                                 col = first_rows$colour,
                                                                 fill = alpha(first_rows$fill, first_rows$alpha),
                                                                 lwd = first_rows$size * .pt,
                                                                 lty = first_rows$linetype
                                                               )
                                            )
                           )
      
      
                         },
      
                         default_aes = aes(colour = "NA", fill = "grey20", size = 0.5, linetype = 1,
                                           alpha = NA, prop = 0.5),
      
                         handle_na = function(data, params) {
                           data
                         },
      
                         required_aes = c("x", "y"),
      
                         draw_key = draw_key_polygon
      )
      

      这里有一些例子。我们可以将三个具有不同 alpha 级别的凸包堆叠在一起,以显示数据中心的位置及其分布:

      ggplot(mpg, aes(displ, hwy, fill = drv, colour = drv)) + 
        geom_point() + 
        geom_bag(prop = 0.95) + # enclose 95% of points
        geom_bag(prop = 0.5,  alpha = 0.5) + # enclose 50% of points
        geom_bag(prop = 0.1, alpha = 0.8) # enclose 5% of points
      

      ggplot(iris, aes(Sepal.Length,  Petal.Length, colour = Species, fill = Species)) + 
        geom_point() + 
        stat_bag(prop = 0.95) +  # enclose 95% of points
        stat_bag(prop = 0.5, alpha = 0.5) + # enclose 50% of points
        stat_bag(prop = 0.05, alpha = 0.9) # enclose 5% of points
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-05
        • 1970-01-01
        • 1970-01-01
        • 2011-08-04
        相关资源
        最近更新 更多