定义路径宽度并计算面积

Define width of a path and calculate area

我使用视频跟踪软件跟踪动物在竞技场中四处走动。数据是动物在 Z 时间(帧数)位置的 X、Y 坐标(以像素为单位)。示例数据框如下所示:

x <- c(1,2,3,4,4,4,4,3,2,1)
y <- c(1,2,3,4,3,2,1,2,3,4)
z <- 1:length(x)
df <- data.frame(x, y, z)

我对动物的行为很感兴趣,想计算一个指标 "area of arena explored." 我不确定最好的方法,但我最初的想法是创建一个逐步路径从点,然后定义一个缓冲宽度到路径以创建多边形,最后,计算多边形下的平面面积。在视觉上,我可以想象这样的东西:

plot(x, y, type = "o", lwd = 20)

我对这些空间数据没有经验,但我 'think' 我可以栅格化这条路径吗?不幸的是,lwd 命令不是绝对的,所以如果我的平面扩展,线宽将不会随之缩放。

我更愿意使用 R 而不是 GIS 软件。

我怀疑有更优雅的解决方案?

我不是研究动物路径的专家,但我认为这是个好主意。

我们可以使用 sf 包,它是 class 的下一代标准和在 R 中分析空间数据的方法。

为了说明它是如何工作的,让我们从一个简单的例子开始。我们将从 c(0, 1)c(1, 1) 画一条线。然后我们将创建一个缓冲区,距离等于1。最后,我们将计算缓冲区的面积。

library(sf)

# Create a simple feature object based on df
ps <- as.matrix(rbind(c(0, 1), c(1, 1)))
ls <- st_linestring(ps)
# View the line
plot(ls)

# Create a buffer zone
ls_buffer <- st_buffer(ls, dist = 1)

# View ls_buffer
plot(ls_buffer)

# Calculate the area
st_area(ls_buffer)
[1] 5.140157

线路和缓冲区看起来不错。我们还可以使用 st_area 函数计算面积。缓冲区的形状类似于一个宽为1、高为2的长方形,加上一个半径为1的圆。我们可以用下面的代码计算面积。结果类似于我们从 st_area 函数得到的结果。

2 * 1 + 1 * 1 * pi
[1] 5.141593

现在,很容易为您的示例修改上述代码。我设置的缓冲距离是0.1,但是你需要确定一个合理的缓冲距离。

# Create example data frame
x <- c(1,2,3,4,4,4,4,3,2,1)
y <- c(1,2,3,4,3,2,1,2,3,4)
z <- 1:length(x)
df <- data.frame(x, y, z)

# Create a simple feature object based on df
ps <- as.matrix(df[, c("x", "y")])
ls <- st_linestring(ps)
# View the line
plot(ls)

# Create a buffer zone
ls_buffer <- st_buffer(ls, dist = 0.1)

# View ls_buffer
plot(ls_buffer)

# Calculate the area
st_area(ls_buffer)
[1] 2.263725

sf 软件包相当新,所以我仍在学习它,可能还有很多我还不知道的功能。如果您想了解更多信息,请访问 CRAN (https://cran.r-project.org/web/packages/sf/index.html) 上的这个软件包网站并访问这些小插图。

此方法涉及 R 中的 GIS 技术,但我认为它相当简单,并遵循您列出的三个步骤。

library(sp)
library(rgeos)
library(dplyr)

#Convert points to path (SpatialLines object)    
SOlines <- Line(coordinates(df[,1:2])) %>% list() %>% Lines(ID="test") %>% list() %>% SpatialLines()
#Buffer the path into a polygon
area <- rgeos::gBuffer(SOlines,width = .1, byid = T) 
#Calculate the area within the Polygon
rgeos::gArea(area,byid=T)
        test 
    2.262897

sf 包(如 ycw 的回答)有一种更直接的创建线路路径的方法。我还不太熟悉那个包,但我暂时保留这个答案,因为使用 SpatialLines 方法的一个好处是您可以在一个对象中存储多条线 (ID),然后在一次调用中计算所有区域gArea