rbindlist用于具有缺失水平的因子。

6

我有几个data.tables需要进行rbindlist操作。这些表格包含了因素(factor),其中可能出现缺失的水平。然后,rbindlist(...)do.call(rbind(...))的行为不同:

dt1 <- data.table(x=factor(c("a", "b"), levels=letters))

rbindlist(list(dt1, dt1))[,x] 
## [1] a b a b
## Levels: a b

do.call(rbind, list(dt1, dt1))[,x]
## [1] a b a b
## Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z

如果我想保留这些级别,是必须使用rbind还是有data.table的方法呢?

4
在调用 rbindlist 函数之前,您可以随时提取级别,然后再将它们放回去(参见这里)。但我认为您说得对,应该有一个 droplevels=TRUE 的参数。 - Justin
2个回答

4
我猜更快是因为它没有检查。为什么不在绑定后设置级别?
    Dt <- rbindlist(list(dt1, dt1)) 
    setattr(Dt$x,"levels",letters)  ## set attribute without a copy

来自?setattr:

setattr()在许多情况下都很有用,可以通过引用设置属性,并且可以用于任何对象或对象的一部分,而不仅仅是data.tables。


谢谢。但是我实际使用这个的地方,我不知道级别。如果我有2个data.tables,我已经需要unique(unlist(lapply(list(dt1, dt2), function(dt) levels(dt[,x]))))来查找级别,我担心do.call(rbind, ...)版本可能会更快。 - shadow
2
@shadow 我猜只有在你有非常多的行和更多的因子水平时才会变慢,这种情况下我会问 - 有什么必要使用因子吗?如果我有一些在数据中反复使用且重复度很高的元素,我才会使用因子。 - eddi
1
就你的情况而言,如果你使用内部的 c.factor 函数,可以大大加快最后一步的速度:do.call(data.table:::c.factor, lapply(list(dt1, dt2), "[[", 'x'))。FWIW。 - eddi

2

感谢指出这个问题。从1.8.11版本开始,已经修复了这个问题:

dt1 <- data.table(x=factor(c("a", "b"), levels=letters))

rbindlist(list(dt1, dt1))[,x]
#[1] a b a b
#Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接