我试图从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包,因为它允许使用插件和平滑交叉验证等方法估计内核分布的带宽。
任何帮助都会非常感激!
答案 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
函数,它似乎在脱节的分布上工作得很好。