我想创建一个面积为100的圆作为sf对象。我原以为st_buffer((可以做到,但面积是略小于100。
pt.df <- data.frame(pt = 1, x = 20, y = 20)
pt.sf <- st_as_sf(pt.df, coords = c("x", "y"))
circle1 <- st_buffer(pt.sf, dist = sqrt(100 / pi))
st_area(circle1) # 99.95431 on my PC
我可以用一个模糊因子乘以半径,得到我想要的。
fudge <- sqrt( 100 / st_area(circle1) )
circle2 <- st_buffer(pt.sf, dist = fudge * sqrt(100 / pi))
st_area(circle2) # 100
但是,使用捏造因素似乎很愚蠢。
有没有一种方法可以在sf包中创建一个已知区域的圆圈st_buffer中的一个伪造因素?
用圆周率的截断形式计算半径是一个浮点精度问题。这将导致一个比你想要的输出稍小的圆圈。你可以看到π只能存储到机器精度:
.Machine$double.eps
# 2.22044604925031e-16
pi
# 3.14159265358979
如果要进行校正,可以对所需区域使用线性校正。请注意,这仍然是一个近似值,但它应该会让你更接近你想要的结果。
radius <- function(area){
A <- area + (area * 0.000457099999999997)
return(sqrt(A / pi))
}
system.file("shape/nc.shp", package="sf") %>%
st_read() %>%
st_centroid() %>%
st_transform(st_crs(5070)) %>%
st_buffer(radius(100)) %>%
st_area()
主要问题是st_buffer
在内部处理多边形,而不是圆形。增加nQuadSegs
参数(默认值=30(可以使用更好的圆近似值,但需要花费内存和计算时间(不知道这对你来说是否重要(:
library(sf)
pt.df <- data.frame(pt = 1, x = 20, y = 20)
pt.sf <- st_as_sf(pt.df, coords = c("x", "y"))
get_area <- function(nq) {
circle1 <- st_buffer(pt.sf, dist = sqrt(100 / pi), nQuadSegs=nq)
st_area(circle1)
}
sapply(c(30,100,300,1000), get_area)
## [1] 99.95431 99.99589 99.99954 99.99996
如果你真的想要一个正好100的区域,那么你的问题(以及@AdamTrevisan的答案(所建议的"捏造"就是你的选择(因为将片段数量增加到100万仍然只能让你达到99.9999999999997200461621的区域(。要想真的聪明,你也许可以用内接多边形面积的公式来计算修正系数。。。