在data.table中对因子级别进行分组

时间:2015-01-27 23:10:04

标签: r data.table

我正在尝试将data.table&想知道是否有data.table - y的方法。

示例:

DT = data.table(id = 1:20, ind = as.factor(sample(8, 20, replace = TRUE)))

我想说类型1,3,8属于A组; 2和4属于B组;和5,6,7属于C组。

以下是我一直在做的事情,这个问题的完整版本速度很慢:

DT[ind %in% c(1, 3, 8), grp := as.factor("A")]
DT[ind %in% c(2, 4), grp := as.factor("B")]
DT[ind %in% c(5, 6, 7), grp := as.factor("C")]

this相关问题建议的另一种方法,我猜这样翻译:

DT[ , grp := ind]
levels(DT$grp) = c("A", "B", "A", "B", "C", "C", "C", "A")
或者或许(考虑到我有65个基础组和18个聚合组,这感觉有点整洁)

DT[ , grp := ind]
lev <- letters(1:8)
lev[c(1, 3, 8)] <- "A"
lev[c(2, 4)] <- "B"
lev[5:7] <- "C"
levels(DT$grp) <- lev

这两个看起来都很笨拙;这似乎是在data.table中执行此操作的合适方法吗?

作为参考,我用10,000,000个观测值和一些更多的子组/超级组等级来加强了这个版本。我最初的方法是最慢的(必须运行所有那些逻辑检查是昂贵的),第二个是最快的,第三个是接近的第二个。但我更喜欢这种方法的可读性。

(在搜索前加密DT可以加快速度,但与后两种方法的差距只有一半)

1 个答案:

答案 0 :(得分:6)

更新

我最近了解了一种更简单的方法,可以将this问题中的因子水平重新关联起来,并仔细阅读?levels。不需要合并,对应表等,只需将名为list的{​​{1}}传递给levels

levels(DT$ind) = list(A = c(1, 3, 8), B = c(2, 4), C = 5:7)

原始答案:

根据@Arun的建议,我们可以选择将对应关系创建为单独的data.table,然后将其加入原始对象:

match_dt = data.table(ind = as.factor(1:12),
                      grp = as.factor(c("A", "B", "A", "B", "C", "C",
                                        "C", "A", "D", "E", "F", "D")))
setkey(DT, ind)
setkey(match_dt, ind)
DT = match_dt[DT]

我们也可以这样做(我认为是这样)更具可读性(如边际速度成本):

levels <- letters[1:12]
levels[c(1, 3, 8)] <- "A"
levels[c(2, 4)] <- "B"
levels[5:7] <- "C"
levels[c(9, 12)] <- "D"
levels[10] <- "E"
levels[11] <- "F"
match_dt <- data.table(ind = as.factor(1:12),
                       grp = as.factor(levels))
setkey(DT, ind)
setkey(match_dt, ind)
DT = match_dt[DT]