数据表无法保留键的解决方法

4

data.table在进行子集操作时不会保留关键字信息

setkey(DT,a,b,c)
key(DT[,list(a,b)]) # return NULL

有人有解决这个问题的方法吗?(其中X Y因此Z是data.table) 实际上我想要做到这一点 =>

Z = X[,list(a, b, c)][Y, mult='last']

注意:我可以做

X2 = X[,list(a, b, c)]
setattr(X2,"sorted",c("a","b","c"))
Z = X2[Y, mult='last']

但我不想将X复制到X2中

编辑示例:

Y = data.table(a=seq(2,4),key="a")
X = data.table(a=seq(1,5),b=seq(2,6),c=sample(letters,5),key="a,b,c")
X[,list(a, b, c)][Y, mult='last']
Error in `[.data.table`(X[, list(a, b, c)], Y, mult = "last") : 
When i is a data.table (or character vector), x must be keyed

更新(eddi):版本1.8.11开始,此问题已得到解决,并在第一个子集中保留了关键字,结果如下:

X[,list(a, b, c)][Y, mult='last']
#   a b c
#1: 2 3 k
#2: 3 4 z
#3: 4 5 u

请提供一个示例以便操作。 - Arun
4
我发现与数据一起工作更容易。而且我不想每次有问题时都创建一个(即使问题很简单)。我会留给别人来回答。 - Arun
@eddi:不错!我一直在使用你下面提到的 with=FALSE 的方式进行此操作。你的更新有点晦涩,因为它需要阅读整篇文章才能理解 key(DT[,list(a,b)]) 的结果更清晰。另外,是否会复制(OP的另一个关注点)?如果可以避免复制,我会感到惊讶... - Frank
@Frank 谢谢,好建议,已经编辑。我认为发生了同样数量的复制,即将列 a、b 和 c 复制。 - eddi
1个回答

4

试试这个:

setkey(X[,list(a, b, c)])[Y, mult='last']

或者,您可以使用 X[Y],然后将 X 的所有其他列设置为 NULL。

X[Y, mult="last"][, c(names_to_remove) := NULL]

1
因为懒惰而受到惩罚...是时候喝咖啡了...我很想给自己的问题投反对票,好在我不能这样做。 - statquant
Arun,@statquant,不太清楚这里发生了什么。我重新打开了一个早先认为已经完成的功能请求,并将其更改为错误状态。#295 保留有序子集后的关键字 - Matt Dowle
@MatthewDowle,我不记得见过这个功能的实现,而且我倾向于在发布时查看“新功能”... - statquant
1
1.8.1版本的新闻中提到:“有序子集现在保留了x的关键字。对于逻辑和带关键字的i,始终如此,并使用base :: is.unsorted()来处理整数和未带关键字的i。实现FR#295。”看起来我做了一些花哨的东西,却忘记了当“i”丢失时的基本情况。 - Matt Dowle
1
另一种选择是:X[, c('a', 'b', 'c'), with = FALSE][Y, mult='last'] - eddi

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