1

我正在研究一个函数,该函数将具有相同列名的数据表列表作为输入并返回一个数据表,该数据表具有使用连续 rbind 组合的每个数据帧的唯一行,如下所示。

该函数将应用于“非常”大的 data.table(数百万行),这就是为什么我必须将其拆分为几个较小的数据表并将它们分配到一个列表中以使用递归的原因。在每一步,根据数据表列表的长度(奇数或偶数),我在该列表索引处找到 data.table 的唯一性,在列表索引 x - 1 处找到数据表,然后连续 rbind 2 并分配列出索引 x - 1,以及更多列出索引 x。

我一定遗漏了一些明显的东西,因为虽然我可以在打印时生成最终的 unique-d data.table(例如 print (listelement[[1]]),但当我返回 (listelement[[1]]) 时,我get NULL. 如果有人能发现我遗漏的东西会有所帮助......或者建议是否有其他更有效的方法来执行此操作。

另外,不必将每个 data.table 添加到列表中,我可以将它们添加为列表中的“引用”吗?我相信像 list(datatable1, datatable2 ...) 这样的事情实际上会复制它们吗?

## CODE
returnUnique2 <- function (alist) {

if (length(alist) == 1) {
  z <- (alist[[1]])
  print (class(z))
  print (z)   ### This is the issue, if I change to return (z), I get NULL (?)
}

if (length(alist) %% 2 == 0) {
  alist[[length(alist) - 1]] <- unique(rbind(unique(alist[[length(alist)]]), unique(alist[[length(alist) - 1]])))
  alist[[length(alist)]] <- NULL
  returnUnique2(alist)
}

if (length(alist) %% 2 == 1 && length(alist) > 2) {
  alist[[length(alist) - 1]] <- unique(rbind(unique(alist[[length(alist)]]), unique(alist[[length(alist) - 1]])))
  alist[[length(alist)]] <- NULL
  returnUnique2(alist)
}  
}


## OUTPUT with print statement
t1 <- data.table(col1=rep("a",10), col2=round(runif(10,1,10)))
t2 <- data.table(col1=rep("a",10), col2=round(runif(10,1,10)))
t3 <- data.table(col1=rep("a",10), col2=round(runif(10,1,10)))
tempList <- list(t1, t2, t3)

returnUnique2(tempList)

[1] "list"
[[1]]
col1 col2
 1:    a    3
 2:    a    2
 3:    a    5
 4:    a    9
 5:    a   10
 6:    a    7
 7:    a    1
 8:    a    8
 9:    a    4
10:    a    6

更改以下内容,

print (z)   ### This is the issue, if I change to return (z), I get NULL (?)

读书

return(z)

返回 NULL

提前致谢。

4

3 回答 3

1

似乎这可能是for循环的一个很好的用例。对于许多行,for与计算时间相比,使用循环的开销应该相对较小。我会尝试将我data.table的 's 组合到一个列表中(ll在我的示例中调用),然后为每个删除重复的行,然后rbinddata.table具有唯一行的前一个,然后再次由唯一行子集。

如果每个块中有许多重复的行,那么这可能会节省一些时间,总的来说我不确定它会有多有效,但值得一试吗?

#  Create empty data.table for results (I have columns x and y in this case)
res <- data.table( x= numeric(0),y=numeric(0))

#   loop over all data.tables in a list called 'll'
for( i in 1:length(ll) ){
    #  rbind the unique rows from the current list element to the results from all previous iterations
    res <- rbind( res , ll[[i]][ ! duplicated(ll[[i]]) , ] )
    #  Keep only unique records at each iteration
    res <- res[ ! duplicated(res) , ]
}

另一方面,您是否查看过文档data.table?它明确指出,

因为 data.tables 通常按 key 排序,所以重复测试特别快。

所以在整个 data.table 上运行可能会更好?

DT[ ! duplicated(DT) , ]
于 2013-06-22T21:46:32.697 回答
1

如果我误解了你在做什么,请纠正我,但听起来你有一个大data.table的并且正试图将它拆分以在其上运行一些功能,然后将所有内容组合回来并在其上运行一个独特的。这样做的data.table方法是使用by,例如

fn = function(d) {
  # do whatever to the subset and return the resulting data.table
  # in this case, do nothing
  d
}

N = 10  # number of pieces you like
dt[, fn(.SD), by = (seq_len(nrow(dt)) - 1) %/% (nrow(dt)/N)][, seq_len := NULL]
dt = dt[!duplicated(dt)]
于 2013-06-24T16:54:25.403 回答
0

为每个 data.table 添加一个 id 列

t1$id=1
t2$id=2
t3$id=3

然后一次将它们组合在一起并使用by=. 如果 data.tables 很大,您可以在调用 unique 之前使用 setkey(...) 在 id 上创建索引。

tall=rbind(t1,t2,t3)
tall[,unique(col1,col2),by=id]
于 2013-06-22T18:16:35.187 回答