【问题标题】:R- Applying a function to each possible pair of rows from two different data-framesR-将函数应用于来自两个不同数据帧的每对可能的行
【发布时间】:2017-06-23 14:25:03
【问题描述】:

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

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)
}
}

谢谢

【问题讨论】:

    标签: r function dataframe combinations vectorization


    【解决方案1】:

    合并两个数据框以获得所有唯一的组合-

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

    【讨论】:

      【解决方案2】:

      您可以创建一个单独的函数来相应地计算每个 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
      

      所以,应用mapply 来迭代函数遍历row_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
      

      【讨论】:

        【解决方案3】:

        还有一个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)]
        

        【讨论】:

          猜你喜欢
          • 2018-12-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-12
          • 1970-01-01
          • 2019-09-07
          • 2022-11-25
          • 1970-01-01
          相关资源
          最近更新 更多