2014-03-28 42 views
0

我必须使用有时返回NULL的函数中的值填充向量(然后data.table)。这个例子说明了什么不顺心:如何保持向量长度和位置,尽管为NULL

library(data.table) 
createNull1 <- function() { # I do not have access to the inside of this function 
    if ((i/2)%%1==0) { return("ABC") } else return(NULL) 
} 

createNull2 <- function() { # I do not have access to the inside of this function 
    if ((i/2)%%1==0) { return(NULL) } else return("XYZ") 
} 

my.data.table <- NULL 
system.time(for (i in 1:10000) { 
my.vector <- c(createNull1(), 
       createNull2(), 
       createNull1(), 
       createNull2(), 
       createNull1()) 
my.data.table <- rbind(my.data.table, data.table(my.vector)) 
}) 

产生的my.data.table有2列,但应该有5.这是为什么:

i <- 1 
my.vector <- c(NULL, "ABC", NULL. "ABC", NULL) # But 2 resulting elements, not 5 
i <- 2 
my.vector <- c("XYZ", NULL, "XYZ", NULL, "XYZ") # But 3 resulting elements, not 5 

我不能编辑的功能,因此该解决方案必须在for循环中找到。

我需要这样做几百万次,所以速度很重要。下面的代码解决了这个问题...

my.data.table <- NULL 
system.time(for (i in 1:10000) { 
    my.vector <- c(if (is.null(createNull1())) NA else createNull1(), 
       if (is.null(createNull2())) NA else createNull2(), 
       if (is.null(createNull1())) NA else createNull1(), 
       if (is.null(createNull2())) NA else createNull2(), 
       if (is.null(createNull1())) NA else createNull1()) 
    my.data.table <- rbind(my.data.table, data.table(my.vector)) 
}) 

...但是速度是两倍以上。

如何更快地创建my.data.table?

+0

为什么你不能编辑功能?无论如何,你的代码很慢,因为你在循环中生成一个对象(阅读[The R Inferno](http://www.burns-stat.com/pages/Tutor/R_inferno.pdf))。它看起来很痛苦,因为你用data.table标记(但实际上不创建data.table)。如果你必须使用'for'循环(为什么?),至少要预先分配矩阵并用子集赋值。 – Roland

+0

是否有你必须使用'NULL'和'NA'的理由? – hrbrmstr

+0

函数来自比我理解的更先进的包。是的,我错过了my.vector周围的data.table()(例如不是真正的代码)。 – Chris

回答

2

尝试预分配和使用set

dt = data.table(a = rep(NA_character_,10000), 
       b = NA_character_, c = NA_character_, 
       d = NA_character_, e = NA_character_) 

for (i in 1:10000) { 
    if (is.null(v1 <- createNull1())) 
    v1 = NA_character_ 
    if (is.null(v2 <- createNull2())) 
    v2 = NA_character_ 

    set(dt, i, 1L, v1) 
    set(dt, i, 2L, v2) 
    set(dt, i, 3L, v1) 
    set(dt, i, 4L, v2) 
    set(dt, i, 5L, v1) 
} 
相关问题