R-将函数应用于来自两个不同数据帧的每对可能的行

时间:2017-06-23 14:25:04

标签: r function dataframe combinations vectorization

我有两个不同的数据帧,行数不同。我需要将一组函数应用于每个可能的行组合,其中一行来自第一个数据帧,另一行来自第二个数据帧。虽然我能够使用 for 循环执行此任务,但我觉得必须有一种更有效的方法来执行此操作。下面给出一个示例案例。 D1和D2是两个数据帧。我需要用一列作为x-y平面中的欧几里德距离来评估D3,将第二列作为z值的平方差来评估D1和D2中的每一行。

D1<-data.frame(x=1:5,y=6:10,z=rnorm(5))
D2<-data.frame(x=19:30,y=41:52,z=rnorm(12))
D3<-data.frame(distance=integer(0),difference=integer(0))

for (i in 1:nrow(D1)){

 for (j in 1:nrow(D2))  {

 temp<-data.frame(distance=sqrt(sum((D1[i,1:2]-D2[j,1:2])^2)),difference=(D1[i,3]-D2[j,3])^2)
D3<-rbind(D3,temp)
}
}

谢谢

3 个答案:

答案 0 :(得分:0)

合并两个数据帧以通过 -

获取所有唯一组合
D3<-merge(D1,D2,by=c())
result<-data.frame(distance=integer(0),difference=integer(0))

然后使用purrr :: map在数据帧D3的所有行中应用相同的距离/差值计算器功能

resdistance<-data.frame(purrr::map(1:nrow(D3),function(ind) { distance=sqrt(sum((D3[ind,]['x.x']-D3[ind,]['x.y'])^2,(D3[ind,]['y.x']-D3[ind,]['y.y'])^2)) }))

resdifference<-data.frame(purrr::map(1:nrow(D3),function(ind) { difference=(D3[ind,]['z.x']-D3[ind,]['z.y'])^2 }))

然后,您可以合并两个数据帧以获得所需的结果

result<-rbind(result,cbind(resdistance,resdifference))

答案 1 :(得分:0)

您可以创建一个单独的函数来相应地计算每个data.frame的索引,这里我称之为i_D1i_D2

# create function to compute the euclidean distance and z-difference
get_D3_values <- function(i_D1, i_D2){
        dist_x <- D1[i_D1, "x"] - D2[i_D2, "x"]
        dist_y <- D1[i_D1, "y"] - D2[i_D2, "y"]

        distance <- sqrt(dist_x^2 + dist_y^2)

        difference <- (D1[i_D1, "z"] - D2[i_D2, "z"])^2


        return(
                list("i_D1"=i_D1, "i_D2"=i_D2, 
                     "distance"=distance, "difference"=difference)
        )
}

之后,创建一个矩阵,将D1D2的所有索引变量与expand.grid合并。

D1 <- data.frame(x=1:5, y=6:10, z=rnorm(5))
D2 <- data.frame(x=19:30, y=41:52, z=rnorm(12))

# create a data table with all combinations between rows of D1 and D2
row_comb <- expand.grid("row_D1"=seq(nrow(D1)), "row_D2"=seq(nrow(D2)))

head(row_comb)

#  row_D1 row_D2
#1      1      1
#2      2      1
#3      3      1
#4      4      1
#5      5      1
#6      1      2

因此,应用mapplyrow_comb的所有行上迭代函数。

result <- with(row_comb, 
               mapply(FUN=get_D3_values, i_D1=row_D1, i_D2=row_D2, USE.NAMES=TRUE))

result <- data.frame(t(result))

head(result)

#  i_D1 i_D2 distance difference
#1    1    1 39.35734 0.08479992
#2    2    1 38.01316   1.155829
#3    3    1 36.67424   2.858793
#4    4    1 35.34119  0.8642712
#5    5    1  34.0147  0.3030355
#6    1    2 40.70626   2.657727

答案 2 :(得分:0)

还有一个data.table解决方案:

library(data.table)
setDT(D1)[, rn := .I]
setDT(D2)[, rn := .I]
D1[D2[CJ(D1$rn, D2$rn), on = .(rn == V2)], on = .(rn == V1)][
  , .(distance = sqrt((x - i.x)^2 + (y -i.y)^2),
      difference = (z - i.z)^2)]