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

时间:2014-01-03 15:11:39

标签: r zoo

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

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

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

geosphere

我想使用hypotenuse <- function(p1,p2) { sqrt((p1[1]-p2[1])^2+(p1[2]-p2[2])^2) } ,但在我看来,我无法将diff函数传递给自定义“差异”函数,所以我的解决方案到现在为止如下:

diff

我阅读了问题A iterative and lagging function similar to diff in R, but not just difference?,并尝试以这种方式使用distances <- c() for(i in 2:nrow(p)) { distances <- c(distances,hypotenuse(p[i,],p[i-1,])) } 包中的rollapply函数:

zoo

但我收到了错误

  

FUN错误(数据[posns],...):
    参数“p2”缺失,没有   默认

因此在我看来,FUN不能是二元函数。

是否可以使用library(zoo) rollapply(p,width=1,FUN=hypotenuse) 功能解决我的问题?

3 个答案:

答案 0 :(得分:5)

以下是一些方法:

> # 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

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

答案 1 :(得分:4)

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

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)

答案 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