递归拆分列表元素

时间:2012-02-01 23:32:31

标签: r

我无法找到ReduceRecalllapply的正确咒语来执行以下任务。考虑以下函数,

bisect.df <- function(d){
  n <- ncol(d)
  if(n%%2) n <- n-1 # drop one col if odd number
  ind <- sample(n)[seq.int(n/2)] # split randomly both parts

  list(first=d[, ind],
       second=d[, -ind])
}

给定data.frame,它会返回一个列表,其中包含从父项中随机提取的两个data.framesncol个孩子。我希望递归地将这个函数应用到子代,直到给定的级别,比如3代。我可以一次只做一代,

bisect.list <- function(l){
  unlist(lapply(l, bisect.df), recursive=FALSE)
}

但是如何递归调用,比如说N=3次?

这是一个与

一起玩的测试样本
d <- data.frame(matrix(rnorm(16*5), ncol=16))
step1 <- bisect.list(list(d))
step2 <- bisect.list(step1)
step3 <- bisect.list(step2)
str(list(step1, step2, step3))

2 个答案:

答案 0 :(得分:2)

bisect.list <- function(l,n){
  for(i in 1:n) {
    l <- unlist(lapply(l, bisect.df), recursive=FALSE)
  }
  return(l)
}

不知道怎么做没有循环...

答案 1 :(得分:2)

这是一个递归解决方案:想法是添加一个参数来计算剩余递归调用的数量。 (但它与循环版本完全相同。)

f <- function( d, n=3 ) {
  if( is.data.frame( d ) )
    return( f( list(d), n ) )
  if( n == 0 )
    return( d )
  result <- lapply( d, bisect.df )
  result <- unlist( result, recursive=FALSE )
  result <- f( result, n-1 )
  result
}
d <- as.data.frame( t(1:20) )
f(d)

随机获取列索引可能更容易 并立即构建所有子data.frame。