紧凑且高效的计算和内存方式来执行迭代或递归子集

时间:2017-08-02 22:21:45

标签: r data.table

我想基于应用于其中一列的条件对data.table dat进行子集化,从而生成子集foobar,然后使用foobar作为子集条件所有列上的dat;冲洗并重复,直到子集为空或经过多次迭代。

以下MWE,其中输入和输出作为注释嵌入,是我当前的解决方案。我想知道是否有更快,更好的内存效率和更紧凑的数据。可行的方法来做到这一点。

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 个答案:

答案 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)