2017-08-02 16 views
1

我想根據應用到它的一列的條件子集data.table dat,產生子集foobar,然後使用foobar作爲子集所有列上dat的條件;沖洗並重復,直到子集爲空或者迭代次數已經過去。緊湊和高效的計算和記憶智慧的方式來做迭代或遞歸子集

以下MWE,輸入和輸出嵌入爲註釋,是我目前的解決方案。我想知道是否有更快,更好的內存有效和更緊湊的data.tableish方式來做到這一點。

library(data.table) 

dat <- data.table(c("a", "a", "", "b", "b", "c", "d"), 
        c(1, 1, 1, 1, 2, 3, 4), 
        c(11, 11, 11, 11, 12, 12, 14), 
        i = 1:7) 
# print(dat) 
# input 
# V1 V2 V3 i 
# 1: a 1 11 1 
# 2: a 1 11 2 
# 3:  1 11 3 
# 4: b 1 11 4 
# 5: b 2 12 5 
# 6: c 3 12 6 
# 7: d 4 14 7 

foobar <- dat[V1 == "a" | V2 == 1 | V3 == -1] 
for (i in 1:5) { 
    baz <- dat[!(i %in% foobar$i) & (V1 %chin% foobar$V1 | V2 %in% foobar$V2 | V3 %in% foobar$V3)] 
    if (nrow(baz) == 0) break 
    foobar <- rbindlist(list(foobar, baz)) 
} 
# print(foobar) 
# output 
# V1 V2 V3 i 
# 1: a 1 11 1 
# 2: a 1 11 2 
# 3:  1 11 3 
# 4: b 1 11 4 
# 5: b 2 12 5 
# 6: c 3 12 6 
+1

這是否回答這樣的問題:https://stackoverflow.com/questions/39623358/collapse-rows-in-data-table-with-lapply-reduce-and-union –

+0

感謝但不害怕,不同的問題 –

回答

1

這裏是你如何可以遞歸做到這一點。我試圖用你已經在使用相同的變量名...

foo <- dat[V1 == "a" | V2 == 1 | V3 == -1] 
counter <- 5 
special <- function(dat, foobar, counter) { 
       if (counter > 0 & nrow(foobar) > 0) { 
       baz <- dat[!(i %in% foobar$i) & (V1 %chin% foobar$V1 | V2 %in% foobar$V2 | V3 %in% foobar$V3)] 
        special(dat, rbindlist(list(foobar,baz)), counter-1) 
       } else { 
        return(foobar) 
       } 
      } 

注意遞歸調用

special(dat, rbindlist(list(foobar,baz)), counter-1) 

哪些更新迭代值和foobar。如果counter==0foobar是空

return(foobar) 
+0

謝謝,是的,這應該是遞歸的方式,不知道它是否更有效率的計算和記憶方面。 –

+0

@JohnSmith我同意 – CPak