Here are two ways to do it. They are both fairly complex conceptually, but actually very simple in code.
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
Explanation
First, the kde(...)
function returns a kde
object, which is a list with 9 elements. You can read about this in the documentation, or you can type str(fhat)
at the command line, or, if you're using RStudio (highly recommended), you can see this by expanding the fhat
object in the Environment tab.
One of the elements is $eval.points
, the points at which the kernel density estimates are evaluated. The default is to evaluate at 151 equally spaced points. $eval.points
is itself a list of, in your case 2 vectors. So, fhat$eval.points[[1]]
represents the points along "Under-5" and fhat$eval.points[[2]]
represents the points along "Ave life exp".
Another element is $estimate
, which has the z-values for the kernel density, evaluated at every combination of x and y. So $estimate
is a 151 X 151 matrix.
If you call kde(...)
with compute.cont=TRUE
, you get an additional element in the result: $cont
, which contains the z-value in $estimate
corresponding to every percentile from 1% to 99%.
So, you need to extract the x- and y-values corresponding to the 95% contour, and use that to calculate the area. You would do that as follows:
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]])
Now, contour.95
has the x- and y-values corresponding to the 95% contour of fhat
. There are (at least) two ways to get the area. One uses the pracma
package and calculates
it directly.
library(pracma)
with(contour.95,polyarea(x,y))
# [1] -113.677
The reason for the negative value has to do with the ordering of x and y: polyarea(...)
is interpreting the polygon as a "hole", so it has negative area.
An alternative uses the area calculation routines in rgeos
(a GIS package). Unfortunately, this requires you to first turn your coordinates into a "SpatialPolygon" object, which is a bit of a bear. Nevertheless, it is also straightforward.
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