2012-02-01 101 views
3

我无法找到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,它返回两个孩子从他们的父母随机抽取同等ncoldata.frames的列表。我希望将这个函数递归地应用到后代,直到一个给定的水平,比如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
bisect.list <- function(l,n){ 
    for(i in 1:n) { 
    l <- unlist(lapply(l, bisect.df), recursive=FALSE) 
    } 
    return(l) 
} 

不知道如何做到这一点没有环......

+0

我的意思是说没有'for'循环,为了调味起来。但是你得到+1是因为它完成了工作:) – baptiste 2012-02-02 00:00:32

+0

我会去for循环,因为它是最容易阅读的。 – baptiste 2012-02-02 01:41:33

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.frames。

+0

好点,事实上,对于我最初的问题,从每个级别的第一个数据帧中抽样可能更有意义。 – baptiste 2012-02-02 01:42:49