如何在data.table中通过引用删除一行?

我的问题是关于分配参考与data.table复制。 我想知道是否可以通过引用删除行,类似于

 DT[ , someCol := NULL] 

我想知道

 DT[someRow := NULL, ] 

我想为什么这个函数不存在是有很好的理由的,所以也许你可以指出一个很好的替代方法,如下所示。 特别是,从我的例子(data.table)最喜欢的,

 DT = data.table(x = rep(c("a", "b", "c"), each = 3), y = c(1, 3, 6), v = 1:9) # xyv # [1,] a 1 1 # [2,] a 3 2 # [3,] a 6 3 # [4,] b 1 4 # [5,] b 3 5 # [6,] b 6 6 # [7,] c 1 7 # [8,] c 3 8 # [9,] c 6 9 

假设我想从这个data.table中删除第一行。 我知道我可以做到这一点:

 DT <- DT[-1, ] 

但是通常我们可能想要避免这种情况,因为我们正在复制对象(并且这需要大约3 * N的内存,如果N object.size(DT) , 这里我指出了 object.size(DT)现在我find了set(DT, i, j, value)我知道如何设置特定的值(如在这里:将行1和2,列2和3中的所有值设置为零)

 set(DT, 1:2, 2:3, 0) DT # xyv # [1,] a 0 0 # [2,] a 0 0 # [3,] a 6 3 # [4,] b 1 4 # [5,] b 3 5 # [6,] b 6 6 # [7,] c 1 7 # [8,] c 3 8 # [9,] c 6 9 

但是我怎么能抹掉前两行呢? 干

 set(DT, 1:2, 1:3, NULL) 

将整个DT设置为NULL。

我的SQL知识是非常有限的,所以你们告诉我:鉴于data.table使用SQL技术,是否有一个相当于SQL命令

 DELETE FROM table_name WHERE some_column=some_value 

在data.table?

好问题。 data.table不能通过引用删除行。

正如你所知, data.table可以通过引用来添加和删除 ,因为它会超出列指针的向量。 计划是做一些类似的行,并允许快速insertdelete 。 行删除将使用C中的memmove来删除行之后的项目(在每一列中)。 与行存储数据库(如SQL)相比,在表中间删除行仍然效率不高,无论行在表中的哪个位置,都更适合快速插入和删除行。 但是,仍然会比复制没有删除行的新大对象快得多。

另一方面,由于列向量将被过度分配,因此行可以即刻插入(并删除) 例如,成长时间序列。

我为了使内存使用类似于就地删除而采取的方法是一次对列进行子集删除。 没有一个适当的C memmove解决scheme,但内存使用是我所关心的在这里。 像这样的东西:

 DT = data.table(col1 = 1:1e6) cols = paste0('col', 2:100) for (col in cols){ DT[, (col) := 1:1e6] } keep.idxs = sample(1e6, 9e5, FALSE) # keep 90% of entries DT.subset = data.table(col1 = DT[['col1']][keep.idxs]) # this is the subsetted table for (col in cols){ DT.subset[, (col) := DT[[col]][keep.idxs]] DT[, (col) := NULL] #delete } 

相反或试图设置为NULL,尝试设置为NA(匹配第一列的NAtypes)

 set(DT,1:2, 1:3 ,NA_character_) 

这是一个基于@ vc273的答案和@弗兰克的反馈工作函数。

 delete <- function(DT, del.idxs) { # pls note 'del.idxs' vs. 'keep.idxs' keep.idxs <- setdiff(DT[, .I], del.idxs); # select row indexes to keep cols = names(DT); DT.subset <- data.table(DT[[1]][keep.idxs]); # this is the subsetted table setnames(DT.subset, cols[1]); for (col in cols[2:length(cols)]) { DT.subset[, (col) := DT[[col]][keep.idxs]]; DT[, (col) := NULL]; # delete } return(DT.subset); } 

其用法举例如下:

 dat <- delete(dat,del.idxs) ## Pls note 'del.idxs' instead of 'keep.idxs' 

其中“dat”是一个data.table。 从我的笔记本电脑上移除1.4M行的14K行需要0.25秒。

 > dim(dat) [1] 1419393 25 > system.time(dat <- delete(dat,del.idxs)) user system elapsed 0.23 0.02 0.25 > dim(dat) [1] 1404715 25 > 

PS。 由于我是新来的SO,我不能添加评论@ vc273的线程:-(

这个话题仍然很有趣(包括我在内)。

那个怎么样? 我用assign来代替glovalenv和之前描述的代码。 捕捉原始的环境会更好,但至less在globalenv环境下,如果它具有内存效率,并且像参考文献中的变化一样。

 delete <- function(DT, del.idxs) { varname = deparse(substitute(DT)) keep.idxs <- setdiff(DT[, .I], del.idxs) cols = names(DT); DT.subset <- data.table(DT[[1]][keep.idxs]) setnames(DT.subset, cols[1]) for (col in cols[2:length(cols)]) { DT.subset[, (col) := DT[[col]][keep.idxs]] DT[, (col) := NULL]; # delete } assign(varname, DT.subset, envir = globalenv()) return(invisible()) } DT = data.table(x = rep(c("a", "b", "c"), each = 3), y = c(1, 3, 6), v = 1:9) delete(DT, 3)