6

[更新 1:正如 Matthew Dowle 所指出的,我data.table在 R-Forge 上使用的是 1.6.7 版本,而不是 CRAN。您不会看到与早期版本相同的行为data.table。]

作为背景:我正在移植一些小实用函数来对数据框的行或数据框对(即每一行是集合中的一个元素)进行集合操作,例如唯一的 - 从列表、联合创建集合,交集,集差等。这些模仿 Matlab 的intersect(...,'rows'),setdiff(...,'rows')等,它们似乎在 R 中没有对应物(R 的集合操作仅限于向量和列表,但不限于矩阵行或数据帧)。这些小功能的示例如下。如果数据框的这个功能已经存在于某些包或基础 R 中,我愿意接受建议。

我一直在将这些迁移到数据表中,当前方法中的一个必要步骤是查找重复的行。执行时duplicated()返回错误,说明数据表必须有键。这是一个不幸的障碍——除了设置键,这不是一个通用的解决方案并增加了计算成本,还有其他方法可以找到重复的对象吗?

这是一个可重现的示例:

library(data.table)
set.seed(0)
x   <- as.data.table(matrix(sample(2, 100, replace = TRUE), ncol = 4))
y   <- as.data.table(matrix(sample(2, 100, replace = TRUE), ncol = 4))

res3    <- dt_intersect(x,y)

产生此错误消息:

Error in duplicated.data.table(z_rbind) : data table must have keys

尽管我用 pattern 命名了每个函数,但该代码对数据帧按原样工作dt_operation

有没有办法解决这个问题?设置键仅适用于整数,这是我不能为输入数据假设的约束。那么,也许我错过了一种使用数据表的聪明方法?


示例集合操作函数,其中集合的元素是数据行:

dt_unique       <- function(x){
    return(unique(x))
}

dt_union        <- function(x,y){
    z_rbind     <- rbind(x,y)
    z_unique    <- dt_unique(z_rbind)
    return(z_unique)
}

dt_intersect    <- function(x,y){
    zx          <- dt_unique(x)
    zy          <- dt_unique(y)

    z_rbind     <- rbind(zy,zx)
    ixDupe      <- which(duplicated(z_rbind))
    z           <- z_rbind[ixDupe,]
    return(z)
}

dt_setdiff      <- function(x,y){
    zx          <- dt_unique(x)
    zy          <- dt_unique(y)

    z_rbind     <- rbind(zy,zx)
    ixRangeX    <- (nrow(zy) + 1):nrow(z_rbind)
    ixNotDupe   <- which(!duplicated(z_rbind))
    ixDiff      <- intersect(ixNotDupe, ixRangeX)
    diffX       <- z_rbind[ixDiff,]
    return(diffX)
}

注意 1:这些辅助函数的一个预期用途是查找 x 中的键值不在 y 中的键值中的行。这样,我可以在计算x[y]或时找到 NA 可能出现的位置y[x]。尽管这种用法允许为z_rbind对象设置键,但我不想将自己限制在这个用例上。

注意 2:对于相关的帖子,这里有一篇关于在数据帧上运行的帖子,使用更新的包unique运行它的结果非常好。data.table这是关于在数据表上运行的早期帖子。unique

4

1 回答 1

7

duplicated.data.table需要得到相同的修复unique.data.table[编辑:现在在 v1.7.2 中完成]。请提出另一个错误报告:bug.report(package="data.table"). 为了其他人的观看,您已经在使用 R-Forge 的 v1.6.7,而不是 CRAN 上的 1.6.6。

但是,在注 1 中,有一个“不加入”成语:

x[-x[y,which=TRUE]]

另请参阅FR#1384(新的 'not' 和 'whichna' 参数?)以使用户更轻松,并链接到与线程不匹配的键,这将更详细。


更新。现在在 v1.8.3 中,已经实现了 not-join。

DT[-DT["a",which=TRUE,nomatch=0],...]   # old idiom
DT[!"a",...]                            # same result, now preferred.
于 2011-10-19T14:39:09.003 回答