是否可以将自定义差分函数传递给 R 的 diff 函数?

  • 本文关键字:函数 diff 是否 自定义 r zoo
  • 更新时间 :
  • 英文 :


我在p中存储了一组 2D 点:

x <- c(0, 1, 2, 3, 4)
y <- c(0, 1, 2, 3, 4)
p <- cbind(x,y)

我需要计算每个连续点之间的距离,我计算距离的函数是hypotenuse(实际上我的问题有点不同,因为我有一个经度、纬度值的列表,我需要使用 geosphere 包中的distVincentyEllipsoid)。

hypotenuse <- function(p1,p2)
{
  sqrt((p1[1]-p2[1])^2+(p1[2]-p2[2])^2)
}

我想使用diff但在我看来,我无法将自定义"差分"函数传递给diff函数,因此到目前为止我的解决方案如下:

distances <- c()
for(i in 2:nrow(p))
{
  distances <- c(distances,hypotenuse(p[i,],p[i-1,]))
}

我读了这个问题 类似于 R 中的 diff 的迭代和滞后函数,但不仅仅是差异? 我尝试以这种方式使用 zoo 包中的 rollapply 函数:

library(zoo)
rollapply(p,width=1,FUN=hypotenuse)

但我收到错误

FUN(data[posns], ...) 中的错误:
缺少参数"P2",没有 违约

所以在我看来,FUN 不能是一个二进制函数。

是否可以使用 rollapply 函数来解决我的问题?

以下是一些方法:

> # 1a
> sqrt(rowSums(diff(p)^2))
[1] 1.414214 1.414214 1.414214 1.414214
> # 1b
> sqrt(diff(p[, 1])^2 + diff(p[, 2])^2)
[1] 1.414214 1.414214 1.414214 1.414214

> # 2a
> library(zoo)
> rollapply(p, 2, dist, by.column = FALSE)
[1] 1.414214 1.414214 1.414214 1.414214
> # 2b
> rollapply(p, 2, function(x) unname(hypotenuse(x[1, ], x[2, ])), by.column = FALSE)
[1] 1.414214 1.414214 1.414214 1.414214
> # 2c
> rollapply(p, 2, function(x) sqrt(sum(diff(x)^2)), by.column = FALSE)
[1] 1.414214 1.414214 1.414214 1.414214

增加:重新排列并添加到解决方案中。

由于这似乎是一个可接受的替代方案,因此您可以对整个计算进行矢量化:

sqrt((p[2:5,1] - p[1:4,1])^2 + (p[2:5,2] - p[1:4,2])^2)

你可以使用 headtail 来概括索引,或者如果你愿意,也可以使用负索引。例如

sqrt((p[-1,1] - p[-nrow(p),1])^2 + (p[-1,2] - p[-nrow(p),2])^2)

我认为这个选项更干净一些,因为您可以将函数分开并且不需要修改函数,如果它是一个复杂的函数,或者如果用户没有直接访问它,这可能会很烦人(就像他感兴趣的实际函数一样):

p.list <- unname(split(p, row(p)))   # `p` is as produced in question
mapply(hypotenuse, head(p.list, -1L), tail(p.list, -1L))
# [1] 1.414214 1.414214 1.414214 1.414214

使用与问题海报相同的hypotenuse。 这里的关键是将原始 p 矩阵转换为包含 x-y 坐标对的列表,然后允许我们使用 mapply .

最新更新