我有一个data.table,我想分成两部分。我这样做如下:
dt <- data.table(a=c(1,2,3,3),b=c(1,1,2,2))
sdt <- split(dt,dt$b==2)
但如果我想将此类事作为下一步
sdt[[1]][,c:=.N,by=a]
我收到以下警告信息。
警告消息:在
[.data.table
(sdt [[1]] ,,:=
(c,.N),by = a): 通过获取副本来检测和修复无效的.internal.selfref 整个表,这样:=可以通过引用添加这个新列。晒黑 早些时候,这个data.table已经被R复制了。避免键&lt; - , 名称&lt; - 和attr&lt; - 当前(并且奇怪地)在R中可以复制整个 data.table。使用set *语法来避免复制:setkey(), setnames()和setattr()。此外,列表(DT1,DT2)将复制整个DT1 和DT2(R的list()复制命名对象),如果使用reflist() 需要(待实施)。如果此消息没有帮助,请 向datatable-help报告,以便修复根本原因。
只是想知道是否有更好的方法来分割表格,以便更有效率(并且不会收到此消息)?
答案 0 :(得分:10)
这适用于v1.8.7(也可能在v1.8.6中工作):
> sdt = lapply(split(1:nrow(dt), dt$b==2), function(x)dt[x])
> sdt
$`FALSE`
a b
1: 1 1
2: 2 1
$`TRUE`
a b
1: 3 2
2: 3 2
> sdt[[1]][,c:=.N,by=a] # now no warning
> sdt
$`FALSE`
a b c
1: 1 1 1
2: 2 1 1
$`TRUE`
a b
1: 3 2
2: 3 2
但是,正如@mnel所说,这是低效的。如果可能的话,请避免分裂。
答案 1 :(得分:4)
我正在寻找一些方法来对data.table进行拆分,我遇到了这个老问题。
有时候你想要做的就是拆分,而data.table&#34; by&#34;方法不方便。
实际上,您可以轻松地使用data.table指令进行拆分,并且它非常有效:
SplitDataTable <- function(dt,attr) {
boundaries=c(0,which(head(dt[[attr]],-1)!=tail(dt[[attr]],-1)),nrow(dt))
return(
mapply(
function(start,end) {dt[start:end,]},
head(boundaries,-1)+1,
tail(boundaries,-1),
SIMPLIFY=F))
}
答案 2 :(得分:1)
如上所述(@jangorecki),软件包data.table
已经具有自己的拆分功能。在这种简化的情况下,我们可以使用:
> dt <- data.table(a = c(1, 2, 3, 3), b = c(1, 1, 2, 2))
> split(dt, by = "b")
$`1`
a b
1: 1 1
2: 2 1
$`2`
a b
1: 3 2
2: 3 2
对于更困难/具体的情况,我建议使用 by reference 函数:=
或set
在data.table中创建一个新变量,然后调用函数split
。如果您关心性能,请确保始终保留在data.table环境中,例如dt[, SplitCriteria := (...)]
,而不是从外部计算spliting变量。