如何从ks R包估计kde对象95%轮廓的面积

时间:2014-09-19 19:00:57

标签: r

我试图从R中的ks包估计kde对象的95%轮廓的面积。

如果我使用ks包中的示例数据集,我将创建内核对象,如下所示:

library(ks)
data(unicef)
H.scv <- Hscv(x=unicef)
fhat <- kde(x=unicef, H=H.scv)

我可以使用绘图功能轻松绘制25,50,75%的轮廓:

plot(fhat)

但我想估计轮廓内的面积。

我看到了类似的问题here,但提出的答案并没有解决问题。

在我的实际应用中,我的数据集是动物坐标的时间序列,我想使用双变量正常内核来测量该动物的家庭范围大小。我使用ks包,因为它允许使用插件和平滑交叉验证等方法估计内核分布的带宽。

任何帮助都会非常感激!

2 个答案:

答案 0 :(得分:4)

以下是两种方法。它们在概念上都相当复杂,但实际上代码非常简单。

fhat <- kde(x=unicef, H=H.scv,compute.cont=TRUE)
contour.95 <- with(fhat,contourLines(x=eval.points[[1]],y=eval.points[[2]],
                                     z=estimate,levels=cont["95%"])[[1]])
library(pracma)
with(contour.95,polyarea(x,y))
# [1] -113.677

library(sp)
library(rgeos)
poly <- with(contour.95,data.frame(x,y))
poly <- rbind(poly,poly[1,])    # polygon needs to be closed...
spPoly <- SpatialPolygons(list(Polygons(list(Polygon(poly)),ID=1)))
gArea(spPoly)
# [1] 113.677

<强>解释

首先,kde(...)函数返回一个kde对象,该对象是一个包含9个元素的列表。您可以在文档中阅读此内容,或者您​​可以在命令行中键入str(fhat),或者,如果您使用RStudio(强烈推荐),您可以通过展开fhat来看到这一点。 “环境”选项卡中的对象。

其中一个元素是$eval.points,即评估核密度估计值的点。默认值是在151个等间隔点进行评估。 $eval.points本身就是一个列表,在您的情况下是2个向量。因此,fhat$eval.points[[1]]代表&#34; Under-5&#34; fhat$eval.points[[2]]表示&#34; Ave life exp&#34;中的点数。

另一个元素是$estimate,其具有核密度的z值,在x和y的每个组合处进行评估。所以$estimate是151 X 151矩阵。

如果您使用kde(...)致电compute.cont=TRUE,则会在结果中获得一个额外元素:$cont,其中包含$estimate中与每个百分位对应的z值1%至99%。

因此,您需要提取与95%轮廓相对应的x值和y值,并使用它来计算面积。你会这样做:

fhat <- kde(x=unicef, H=H.scv,compute.cont=TRUE)    
contour.95 <- with(fhat,contourLines(x=eval.points[[1]],y=eval.points[[2]],
                                     z=estimate,levels=cont["95%"])[[1]])

现在,contour.95的x值和y值对应fhat的95%轮廓。有(至少)两种方式来获得该区域。一个使用pracma包并计算  直接。

library(pracma)
with(contour.95,polyarea(x,y))
# [1] -113.677

负值的原因与x和y的排序有关:polyarea(...)将多边形解释为&#34;孔&#34;,因此它具有负面积。

另一种方法是使用rgeos(GIS包)中的区域计算例程。不幸的是,这需要您首先将坐标转换为&#34; SpatialPolygon&#34;对象,这有点像熊。尽管如此,它也很简单。

library(sp)
library(rgeos)
poly <- with(contour.95,data.frame(x,y))
poly <- rbind(poly,poly[1,])    # polygon needs to be closed...
spPoly <- SpatialPolygons(list(Polygons(list(Polygon(poly)),ID=1)))
gArea(spPoly)
# [1] 113.677

答案 1 :(得分:0)

另一种方法是在kde包中使用size_t offset = offsetof(struct name, member); 函数。我也有兴趣使用这个软件包来比较生态学中的2D和3D空间使用,但我不确定如何提取2D密度估计。我通过估计动物的面积测试了这种方法。它仅限于具有已知半径的圆的区域。以下是代码:

contourSizes()

我还尝试创建2个未连接的圈子并测试set.seed(123) require(GEOmap) require(kde) # need this library for the inpoly function # Create a data frame centered at coordinates 0,0 data = data.frame(x=0,y=0) # Create a vector of radians from 0 to 2*pi for making a circle to # test the area circle = seq(0,2*pi,length=100) # Select a radius for your circle radius = 10 # Create a buffer for when you simulate points (this will be more clear below) buffer = radius+2 # Simulate x and y coordinates from uniform distribution and combine # values into a dataframe createPointsX = runif(1000,min = data$x-buffer, max = data$x+buffer) createPointsY = runif(1000,min = data$y-buffer, max = data$y+buffer) data1 = data.frame(x=createPointsX,y=createPointsY) # Plot the raw data plot(data1$x,data1$y) # Calculate the coordinates used to create a cirle with center 0,0 and # with radius specified above coords = as.data.frame(t(rbind(data$x+sin(circle)*radius, data$y+cos(circle)*radius))) names(coords) = c("x","y") # Add circle to plot with red line lines(coords$x,coords$y,col=2,lwd=2) # Use the inpoly function to calculate whether points lie within # the circle or not. inp = inpoly(data1$x, data1$y, coords) data1 = data1[inp == 1,] # Finally add points that lie with the circle as blue filled dots points(data1$x,data1$y,pch=19,col="blue") # Radius of the circle (known area) pi * radius^2 #[1] 314.1593 # Sub in your own data here to calculate 95% homerange or 50% core area usage H.pi = Hpi(data1,binned=T) fhat = kde(data1,H=H.pi) ct1 = contourSizes(fhat, cont = 95, approx=TRUE) # Compare the known area of the circle to the 95% contour size ct1 # 5% # 291.466 函数,它似乎在脱节的分布上工作得很好。