使用purrr :: cross_n过滤笛卡尔积

时间:2016-02-22 19:34:58

标签: r purrr

我尝试了一些purrr成语 - 特别是循环(或者如果你愿意应用)的函数通过一个data.frame运行并与另一个data.frame中的所有其他行进行比较......并根据该比较函数过滤笛卡尔积。

> df1    
        chr start   end
      (fctr) (int) (int)
    1   chr1  9069  9176
    2   chr1 10460 11368
    3   chr1 34633 35625
    4   chr1 36791 37023
> df2
     chr start2
  (fctr) (dbl)
1   chr1  9169
2   chr1 10360
3   chr1 34633

所以一个简单的示例函数是:

> is.between <- function(x1, y1, y2){
  ifelse(x1 >= y1 & x1 <= y2, TRUE, FALSE)
}

我正在寻找的结果(现在)应该是2乘4的数据。df3喜欢

             # desired result
             chr start  end  start2
          (fctr) (int) (int)
        1   chr1  9069  9176  9169
        2   chr1  34633 35625 34633

天真然后我尝试使用purrr::cross_n函数,就像这样......

> cross_n(list(df2$start2, df1$start, df1$start), .filter = is.between)

当然,它不起作用,它正在搜索3个输入列(48种组合)的笛卡尔积。我希望搜索df2$start2与[df1$startdf1$end](12种组合)的组合。

所以......有没有办法在purrr框架内做到这一点?

无法使用cross_ncross2并且错误地了解它...我不完全理解cross_d上的文档

1 个答案:

答案 0 :(得分:1)

好的FWIW - 我已经调整了一些purrr::cross_n函数来回答我自己的问题。新函数cross2d如下所示:

# this makes sense only if the .l in the same groups are the same length
# ie they are probably from the same data.frame
cross2d<- function(.l, groups = NULL, .filter = NULL){
  if (is_empty(.l) | is.null(groups)) {
    return(.l)
  }
  if (!is.null(.filter)) {
    .filter <- as_function(.filter)
  }

  n <- length(.l)

  #separate df for each group
  df1<- data.frame(.l[groups==0])
  df2<- data.frame(.l[groups==1])


  exp.coords<-expand.grid(1:nrow(df1), 1:nrow(df2))
  df<- data.frame(df1[exp.coords$Var1,], df2[exp.coords$Var2,])
  names(df)<-c(colnames(df1),colnames(df2))

  df[do.call(.filter, unname(df)),]
}

使用上面显示的示例数据df1df2以及is.between函数,您可以像这样使用它:

> cross2d(list(x1=df2$start, x2=df1$start, y2=df1$end), group=c(0,1,1), .filter=is.between)
       x1    x2    y2
1    9169  9069  9176
3.2 34633 34633 35625

我已经为2组(data.frames)和data.frame输出编码了这个..但它可能会进一步推广......?