拆分data.table

时间:2013-02-20 10:50:54

标签: r data.table

我有一个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报告,以便修复根本原因。

只是想知道是否有更好的方法来分割表格,以便更有效率(并且不会收到此消息)?

3 个答案:

答案 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变量。