split和data.table的问题

时间:2015-12-29 13:49:26

标签: r split data.table

我有一个data.table,我想拆分成一个列表然后修改。当我在调用split后尝试删除列表中某个data.tables上的列时,我发现了一些奇怪的行为。这是一个MWE(抛出错误并导致我的R会话崩溃):

library(data.table)
d = data.table(level = c(1, 1, 2, 2), value = 1:4)
list = split(d, f = d$level)
list[[1]][, level := NULL]
list

我明白了:

Error in .shallow(x, cols = cols, retain.key = TRUE) : Internal error: length(names)>0 but <length(dt)

1 个答案:

答案 0 :(得分:2)

我建议使用l名称作为变量,而不是list 这似乎是由进程中使用的split.data.frame方法引起的错误 我最近提出了一个新的split.data.table方法,定义如下。它似乎解决了你的问题。

更新2016-03-30:

split.data.table已在data.table 1.9.7中实现。现在使用可以简单地使用:

library(data.table)
d = data.table(level = c(1, 1, 2, 2), value = 1:4)
l = split(d, by = "level")
l[[1L]][, level := NULL]
l
#$`1`
#   value
#1:     1
#2:     2
#
#$`2`
#   level value
#1:     2     3
#2:     2     4

下面的旧答案,如果你坚持使用1.9.6或更低版本可能会有用。请注意,它不会像split.data.frame那样处理因子级别,而在data.table 1.9.7中开发的方法不是这种情况,这与data.frame方法一致。

library(data.table)
split.data.table = function(x, f, drop = FALSE, by, flatten = FALSE, ...){
    if(missing(by) && !missing(f)) by = f
    stopifnot(!missing(by), is.character(by), is.logical(drop), is.logical(flatten), !".ll" %in% names(x), by %in% names(x))
    if(!flatten){
        .by = by[1L]
        tmp = x[, list(.ll=list(.SD)), by = .by, .SDcols = if(drop) setdiff(names(x), .by) else names(x)]
        setattr(ll <- tmp$.ll, "names", tmp[[.by]])
        if(length(by) > 1L) return(lapply(ll, split.data.table, drop = drop, by = by[-1L])) else return(ll)
    } else {
        tmp = x[, list(.ll=list(.SD)), by=by, .SDcols = if(drop) setdiff(names(x), by) else names(x)]
        setattr(ll <- tmp$.ll, 'names', tmp[, .(nm = paste(.SD, collapse = ".")), by = by, .SDcols = by]$nm)
        return(ll)
    }
}
d = data.table(level = c(1, 1, 2, 2), value = 1:4)
l = split.data.table(d, by = "level")
# below setattr to be addressed in split.data.table
invisible(lapply(l, setattr, ".data.table.locked", NULL))
l[[1]][, level := NULL]
l
#$`1`
#   value
#1:     1
#2:     2
#
#$`2`
#   level value
#1:     2     3
#2:     2     4

我还填写了一份描述您案例的错误报告,您可以在data.table#1481找到它。