r语言 - Issue with split and 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)

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

更新2016-03-30:

split.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那样处理因子水平,数据表1.9.7中开发的方法与数据帧方法不一致。

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中找到它。

最新更新