如何在R中使用使用两列的自定义函数进行聚合

Qui*_*ter 3 aggregate r distance

是否可以使用使用两列返回一列的自定义函数进行聚合?

假设我有一个数据帧:

x <- c(2,4,3,1,5,7)
y <- c(3,2,6,3,4,6)
group <- c("A","A","A","A","B","B")

data <- data.frame(group, x, y)
data
#   group x y
# 1     A 2 3
# 2     A 4 2
# 3     A 3 6
# 4     A 1 3
# 5     B 5 4
# 6     B 7 6
Run Code Online (Sandbox Code Playgroud)

我有我想要在两列(x和y)上使用的函数:

pathlength <- function(xy) {
  out <- as.matrix(dist(xy))
  sum(out[row(out) - col(out) == 1])
}
Run Code Online (Sandbox Code Playgroud)

我用聚合尝试了以下内容:

out <- aggregate(cbind(x, y) ~ group, data, FUN = pathlength)  
out <- aggregate(cbind(x, y) ~ group, data, function(x) pathlength(x))  
Run Code Online (Sandbox Code Playgroud)

但是,这会分别在x和y上调用pathlength而不是在一起,这给了我:

#  group x y
#1     A 5 8
#2     B 2 2
Run Code Online (Sandbox Code Playgroud)

我想要的是在x和y上调用pathlength并以这种方式聚合它.这是我想要聚合做的事情:

realA <- matrix(c(2,4,3,1,3,2,6,3), nrow=4, ncol=2)
pathlength(realA)
# [1] 9.964725

realB <- matrix(c(5,7,4,6), nrow=2, ncol=2)
pathlength(realB)
# [1] 2.828427

group <- c("A", "B") 
pathlength <- c(9.964725,2.828427)
real_out <- data.frame(group, pathlength)
real_out
#   group pathlength
# 1     A   9.964725
# 2     B   2.828427
Run Code Online (Sandbox Code Playgroud)

有没有人有什么建议?或者是否有一些我在谷歌上找不到的其他功能让我这样做?我宁愿不使用for循环来解决这个问题,因为我认为它对于大数据集来说会很慢.

MrF*_*ick 6

如您所知,基本aggregate()功能一次只能在一列上运行.相反,你可以使用该by()功能

by(data[,c("x","y")], data$group, pathlength)
data$group: A
[1] 9.964725
----------------------------------------------------------------------- 
data$group: B
[1] 2.828427
Run Code Online (Sandbox Code Playgroud)

要么 split()/lapply()

lapply(split(data[,c("x","y")], data$group), pathlength)
$A
[1] 9.964725

$B
[1] 2.828427
Run Code Online (Sandbox Code Playgroud)

  • 或者`stack(lapply(split(data [-1],data [1]),pathlength))` (3认同)