计算R中不规则形状的面积

Calculating the area of irregular shape in R

我想计算 R 中的封闭区域,如下图所示:

密码是:

a <- c(0,1,2,2,1,0,-1,-2,-2,-1,0)
b <- c(0,0,0,1,0,0,0,0,1,0,0)
id <- order(a)
AUC <- sum(abs(diff(a[id])*rollmean(b[id],2)))

AUC 的结果是 0.5。为什么不是 1?

当我做同样的事情,但针对不同的向量时,第二个例子: 代码是:

a <- c(0,1,1,0,0,0,1,1,0,0,0)
b <- c(1,1,2,1,0,-1,-1,-2,-1,0,1) 
id <- order(a) 
AUC <- sum(abs(diff(a[id])*rollmean(b[id],2)))

结果是1,符合我的预期。

最后一个最重要的问题是: 我在数据框中有 2 列 x 和 y(100 行,2 列),当绘制 x 与 y 时,它们形成不规则形状(圆图)的闭合曲线,如下图所示: 我想使用 2 列 x 和 y 计算该形状的面积。有办法吗?

更新: 第三个例子(循环图)的数据是:

structure(c(-0.317857301365341, -0.27254852000745, -0.239116190750992, 
-0.212617899743053, -0.188665601384051, -0.164652457277714, -0.516811363687365, 
-0.704142203990645, -0.925833008271225, -1.17644987082148, -1.44698060870818, 
-1.72501192276032, -1.99567842934217, -2.24329812421979, -2.45336219338653, 
-2.61434899714043, -2.71894439436842, -2.76453987881648, -2.75307392975534, 
-2.69034804478649, -2.58498022688992, -2.44717942836848, -2.28751639917794, 
-2.11583498227994, -1.94040889261091, -1.76740411983085, -1.37034128566268, 
-0.945317248194438, -0.603583991912112, -0.245876237842544, 0.12405281597095, 
0.500705070183803, 1.07928003293753, 1.3786192588209, 1.93625569819096, 
2.32102987210859, 2.67667485884349, 2.9817217810439, 3.21508203608072, 
3.35805065942255, 3.39629843099713, 3.32158207702952, 3.13297595252244, 
2.83749468084523, 2.44998880428773, 1.99219777869042, 1.34133852767483, 
0.905097245217795, 0.332495432968877, 0.000565676359279427, -0.304679355313777, 
-0.676576930379378, -0.799504493858939, -0.877037748519715, -0.907917643885644, 
-0.895574022744618, -0.847333419315191, -0.773304922267926, -0.68506594358595, 
-0.594261154658402, -0.511242949335073, -0.443908244418344, -0.396899995824444, 
-0.371311027504522, -2.95318107124334, -2.91494448796198, -2.80017869044755, 
-2.61894793180667, -2.38576761259564, -2.11805651326137, -1.41368736155233, 
-0.896608829738209, -0.363137342157785, 0.165324041578864, 0.668413502524084, 
1.12765173596156, 1.52716559439287, 1.85443533430032, 2.10104197466128, 
2.26318484127474, 2.34177274880676, 2.34207035998987, 2.2729829455437, 
2.14607786936849, 1.97445291610407, 1.77157880225516, 1.5502403566333, 
1.32167995293426, 1.09501806084454, 0.876985405337858, 0.780951474855999, 
0.715653776169357, 0.631076472349792, 0.572023400386015, 0.534441560957589, 
0.513328184556074, 0.275997813967411, 0.34478353180991, 0.504249489908016, 
0.587434743269948, 0.654235885315243, 0.701450060739606, 0.72746455454756, 
0.732567090012129, 0.718940924224628, 0.690264488986728, 0.650927827300914, 
0.604983707715769, 0.555050419060634, 0.501440460475964, 0.370959009632643, 
0.337726723524854, 0.216270960220213, 0.162458598954556, 0.060364386887637, 
-0.136702597984821, -0.309488796931729, -0.535968167790145, -0.807754519418657, 
-1.11285625385781, -1.43643730574278, -1.76172554792592, -2.0710195962479, 
-2.34678141009815, -2.57280751486803, -2.73543188753935, -2.82464965255479, 
-2.83501170706251), .Dim = c(64L, 2L), .Dimnames = list(c("309", 
"310", "311", "312", "313", "314", "315", "316", "317", "318", 
"319", "320", "321", "322", "323", "324", "325", "326", "327", 
"328", "329", "330", "331", "332", "333", "334", "335", "336", 
"337", "338", "339", "340", "341", "342", "343", "344", "345", 
"346", "347", "348", "349", "350", "351", "352", "353", "354", 
"355", "356", "357", "358", "359", "360", "361", "362", "363", 
"364", "365", "366", "367", "368", "369", "370", "371", "372"
), c("PC1", "PC2"))) 

不确定您使用的方法是什么以及为什么在这种情况下不起作用。
另一种方法是使用 sf (simple features),它处理面积计算:

library(sf)  

a <- c(0,1,2,2,1,0,-1,-2,-2,-1,0)
b <- c(0,0,0,1,0,0,0,0,1,0,0)

poly <- st_polygon(list(cbind(a,b)))
poly <- st_make_valid(poly)
plot(poly)

st_area(poly)
#> [1] 1

请注意 st_make_valid 的使用,因为 多边形应该是不相交的 ,在您提供的三个示例中并非如此。
在第一个示例中,多边形转换为 2 个多边形和 2 个线串:

st_make_valid(poly)
GEOMETRYCOLLECTION (MULTIPOLYGON (((-2 1, -1 0, -2 0, -2 1)), ((2 0, 1 0, 2 1, 2 0))), 
                    MULTILINESTRING ((0 0, -1 0), (0 0, 1 0)))

对于圆图,如果你想要一个精确的面积,就需要轨迹的交点,而你提供的数据并不是这样。
作为近似值,您可以使用 concaveman:

library(concaveman)
st_polygon(list(concaveman(data)))

plot(st_polygon(list(concaveman(data))), col='grey')
plot(st_linestring(data),add=T,col='red')

st_area(st_polygon(list(concaveman(data))))
[1] 2.693168