【问题标题】:plotting a curve around a set of points围绕一组点绘制曲线
【发布时间】:2012-11-27 05:28:37
【问题描述】:

我在飞机上有一组点。它们被划分为子集。 我想在属于同一子集的点周围绘制一条闭合曲线,这样属于子集的点将在曲线内,而不属于子集的点将在曲线外。因此,简单的圆或凸包可能不起作用。

首先,假设我只想在一组点周围有一条平滑曲线(不要求它排除其他点)

任何想法如何在 R 中做到这一点?

---稍后添加---

我最终看到的是这里的图形精神:https://tex.stackexchange.com/questions/1175/drawing-a-hypergraph - 虽然上下文不是超图,而是一组给定的点和这些点的分区。

【问题讨论】:

  • 当您说平滑曲线时,您的意思是凸包不起作用(对于您正在谈论的入门问题)?
  • 出于美学原因,我更喜欢比凸包多边形更平滑的曲线。当然,对于初学者问题,一个简单的解决方案是找到一个包含所有点的足够大的圆圈。但是这个解决方案不能应用于/扩展到一般问题。我试图找到一些更贴近给定点集的点。
  • @amit - 你可以使用Hmisc 库中的bezier 来平滑chull 多边形吗?
  • @thelatemail:我不确定这是否能保证多边形中的所有点都在曲线内,尽管我可能是错的
  • 我不确定,但可以将问题表述为带有计数图的 KNN 问题

标签: r graphics2d curve


【解决方案1】:

好的,这是我认为接近您所追求的答案的版本: 它使用在 GIS 论坛上的这个答案 (https://gis.stackexchange.com/a/24929) 上创建的 spline.poly 函数。

这里有一些例子:

testpts <- 
structure(list(x = c(4.9, 4.2, 4, 4.1, 4.4, 5.8, 5.8, 5.8, 5.8, 
5.5, 4.9, 3.2, 3.2, 3.3, 5.4, 5.4, 5.7, 6.4, 6.7, 6.7, 6, 4.8, 
3.6, 2.8, 3.5, 4.4, 5.1, 4, 3.7, 4.5, 4.9, 5.7), y = c(6.9, 6.2, 
5.3, 4.1, 3.1, 2.9, 2.9, 3.5, 4.2, 4.9, 5.1, 4.9, 4.9, 5.2, 6.9, 
6.9, 5.3, 3.8, 4.2, 5.6, 6.9, 5.8, 1.2, 2.5, 5.3, 6.4, 6.8, 7.6, 
6.9, 5.4, 4.8, 4.4)), .Names = c("x", "y"))

设置基本情节

plot(NA,xlim=c(0,10),ylim=c(0,10))
points(testpts,pch=19)
chuld <- lapply(testpts,"[",chull(testpts))
polygon(chuld,lty=2,border="gray")
polygon(spline.poly(as.matrix(as.data.frame(chuld)),100),border="red",lwd=2)

结果:

编辑以添加凹面示例

这部分答案使用alphahull

# load the required library
library(alphahull)

plot(NA,xlim=c(0,10),ylim=c(0,10))
points(testpts,pch=19)
# remove duplicate points so the ahull function doesn't error out
testptsnodup <- lapply(testpts,"[",which(!duplicated(as.matrix(as.data.frame(testpts)))))

生成并绘制 ahull 对象 - alpha 值似乎对于确定多边形与数据的拟合非常重要。

ahull.obj <- ahull(testptsnodup,alpha=2)
plot(ahull.obj,add=TRUE,col="red",wpoints=FALSE)

结果:

【讨论】:

  • 这是一个不错的解决方案!我认为曲线仍然相当“大”,因为它是基于凸包的,因此很难“排除”不属于集合的点。但是 spline.poly 也可以用于凹多边形。我只需要计算那个多边形。谢谢。
  • @amit - 您可能会对此包感兴趣:cran.r-project.org/web/packages/alphahull/index.html,我在 GIS stackexchange 上的这个问题上再次找到链接:gis.stackexchange.com/questions/1200/…
  • @amit - 我已经合并了一个显示凹解决方案的新示例。如果它看起来像你想要的,请告诉我。
  • 有一个函数rgeos::gBuffer 可以将多边形“增长”一定数量。这可以帮助 OP 接近提供的链接中的问题。
【解决方案2】:

ggalt 包提供 geom_encircle,它应该提供类似这样的东西 - 凸面,但平滑:

library(ggplot2)
library(ggalt)  ## v 0.4.0

df <- data.frame(x = rnorm(20), y = rnorm(20),
      z = sample(letters[1:5], 20, replace = TRUE))
ggplot(df, aes(x, y, colour = z)) + geom_point() +
     geom_encircle(aes(fill=z),alpha=0.3)

【讨论】:

    【解决方案3】:

    经过一番谷歌搜索,我对这个例子稍作修改Morota ggplot2

    编辑

    它使用 chull 函数和 bezier

    library(ggplot2)
    library(plyr)
    library(Hmisc)
    
    
    
    df <- data.frame(x = rnorm(20), y = rnorm(20),z = sample(letters[1:5], 20, rep = T))
    ggplot(df, aes(x, y, colour = z)) + geom_point()
    
    find_hull <- function(df) {
        res.ch <- df[chull(df$x, df$y), ]
        res <- bezier(res.ch)
        res <- data.frame(x=res$x,y=res$y)
        res$z <- res$z
        res
      }
    hulls <- ddply(df, "z", find_hull)
    ggplot(df, aes(x, y, colour = z,fill = z)) +
      geom_point() + geom_polygon(data = hulls,alpha = 0.4)
    

    【讨论】:

    • 不过,这不会像 OP 要求的那样顺利
    • @David 现在更流畅了。
    • 我认为您的原始答案更好。虽然更流畅,但这个结果似乎漏掉了一些要点。
    • 我认为这也是因为我随机生成了我的数据。我在你的代码中用 bezier 替换了 spline.poly,我几乎得到了你的结果。我对我的 2 个解决方案不满意...我稍后尝试将其表述为近邻问题。
    【解决方案4】:

    简单地说:

    testpts <- structure(list(x = c(4.9, 4.2, 4, 4.1, 4.4, 5.8, 5.8, 5.8, 5.8, 
    5.5, 4.9, 3.2, 3.2, 3.3, 5.4, 5.4, 5.7, 6.4, 6.7, 6.7, 6, 4.8, 
    3.6, 2.8, 3.5, 4.4, 5.1, 4, 3.7, 4.5, 4.9, 5.7), y = c(6.9, 6.2, 
    5.3, 4.1, 3.1, 2.9, 2.9, 3.5, 4.2, 4.9, 5.1, 4.9, 4.9, 5.2, 6.9, 
    6.9, 5.3, 3.8, 4.2, 5.6, 6.9, 5.8, 1.2, 2.5, 5.3, 6.4, 6.8, 7.6, 
    6.9, 5.4, 4.8, 4.4)), .Names = c("x", "y"))
    x <- do.call('cbind',testpts)
    ch<-chull(x)
    x[c(ch,ch[1]),]
    plot(x,pch=20)
    points(x[ch,],pch=20,col='red')
    lines(x[c(ch,ch[1]),],lwd=.5)
    

    剧情:

    【讨论】:

    • OP 不想要一个 chull:“因此 [...] 凸包可能不起作用。”
    猜你喜欢
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 2017-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多