2012-02-01 177 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