I have a set of points on a plane. They are partitioned into subsets. I want to plot a closed curve around points that belong to the same subset, so that points that belong to a subset will be inside the curve, and those that aren't will be outside. Therefore simple circles, or a convex hull might not work.
我在飞机上有一套点。它们被划分为子集。我想围绕属于同一子集的点绘制闭合曲线,以便属于子集的点将位于曲线内部,而不属于该子集的点将位于外部。因此,简单的圆圈或凸包可能不起作用。
For a starter, let's say I just want to have a smooth curve around a set of point (without the requirement that it excludes other points)
对于初学者,假设我只想在一组点附近有一条平滑的曲线(不要求它排除其他点)
Any ideas how to do that in R?
任何想法如何在R?
---added later---
---后来补充---
What I'm looking eventually, is something in the spirit of the graphics in here: https://tex.stackexchange.com/questions/1175/drawing-a-hypergraph - although the context is not a hypergraph, but rather a given set of points and a partition of those.
我最终看到的是这里的图形精神:https://tex.stackexchange.com/questions/1175/drawing-a-hypergraph - 虽然上下文不是超图,而是给定的点集和那些分区。
4 个解决方案
#1
21
Okay, here's a version of an answer that I think gets close to what you are chasing: It uses the spline.poly
function created over at this answer ( https://gis.stackexchange.com/a/24929 ) on the GIS forum.
好的,这是我认为接近您追逐的答案的一个版本:它使用在GIS论坛上创建的spline.poly函数(https://gis.stackexchange.com/a/24929) 。
Here's some example points:
以下是一些示例点:
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"))
Set up a basic plot
设置基本情节
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)
And the result:
结果如下:
EDIT TO ADD A CONCAVE EXAMPLE
编辑添加一个凹凸的例子
This part of the answer uses the alphahull
library
这部分答案使用了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)))))
Generate and plot the ahull object - the alpha value seems to be very important in determining the fit of the polygon to the data.
生成并绘制ahull对象 - 在确定多边形与数据的拟合时,alpha值似乎非常重要。
ahull.obj <- ahull(testptsnodup,alpha=2)
plot(ahull.obj,add=TRUE,col="red",wpoints=FALSE)
And the result:
结果如下:
#2
5
The ggalt
package provides geom_encircle
, which is supposed to provide something like this - convex, but smooth:
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
3
After some googling, I little modify this example Morota ggplot2
经过一些谷歌搜索,我很少修改这个例子Morota ggplot2
EDIT
编辑
It uses the chull function with bezier
它使用bezier的chull函数
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)
#4
0
Simply:
只是:
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)
Plot:
情节:
剧情
#1
21
Okay, here's a version of an answer that I think gets close to what you are chasing: It uses the spline.poly
function created over at this answer ( https://gis.stackexchange.com/a/24929 ) on the GIS forum.
好的,这是我认为接近您追逐的答案的一个版本:它使用在GIS论坛上创建的spline.poly函数(https://gis.stackexchange.com/a/24929) 。
Here's some example points:
以下是一些示例点:
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"))
Set up a basic plot
设置基本情节
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)
And the result:
结果如下:
EDIT TO ADD A CONCAVE EXAMPLE
编辑添加一个凹凸的例子
This part of the answer uses the alphahull
library
这部分答案使用了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)))))
Generate and plot the ahull object - the alpha value seems to be very important in determining the fit of the polygon to the data.
生成并绘制ahull对象 - 在确定多边形与数据的拟合时,alpha值似乎非常重要。
ahull.obj <- ahull(testptsnodup,alpha=2)
plot(ahull.obj,add=TRUE,col="red",wpoints=FALSE)
And the result:
结果如下:
#2
5
The ggalt
package provides geom_encircle
, which is supposed to provide something like this - convex, but smooth:
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
3
After some googling, I little modify this example Morota ggplot2
经过一些谷歌搜索,我很少修改这个例子Morota ggplot2
EDIT
编辑
It uses the chull function with bezier
它使用bezier的chull函数
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)
#4
0
Simply:
只是:
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)
Plot:
情节:
剧情