我的问题与 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)
# x y v
# [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)
,as pointed out here . 现在我找到 set(DT, i, j, value)
. 我知道如何设置特定值(如下所示:设置所有值)在第1行和第2行以及第2列和第3列为零)
set(DT, 1:2, 2:3, 0)
DT
# x y v
# [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?
6 回答
为了使内存使用类似于就地删除,我采取的方法是一次对列进行子集并删除 . 没有正确的C memmove解决方案快,但内存使用是我在这里所关心的 . 像这样的东西:
好问题 .
data.table
无法通过引用删除行 .data.table
可以通过引用添加和删除列,因为它会过度分配列指针的向量,如您所知 . 计划是为行做类似的事情并允许快速insert
和delete
. 行删除将使用C中的memmove
来删除已删除行之后的项目(在每一列中) . 与诸如SQL之类的行存储数据库相比,删除表中间的行仍然是非常低效的,这更适合于快速插入和删除表中这些行的任何位置 . 但是,它仍然比复制没有删除行的新大对象快得多 .另一方面,由于列向量将被过度分配,因此可以在最后立即插入(和删除)行;例如,不断增长的时间序列 .
它是一个问题:Delete rows by reference .
这是一个基于@ vc273的答案和@Frank的反馈的工作函数 .
其用法示例:
“dat”是data.table . 从我的笔记本电脑上删除1.4M行中的14k行需要0.25秒 .
PS . 由于我是SO的新手,我无法在@ vc273的帖子中添加评论:-(
而是尝试设置为NULL,尝试设置为NA(匹配第一列的NA类型)
很多人(包括我在内)这个话题仍然很有趣 .
那个怎么样?我用
assign
替换glovalenv
和前面描述的代码 . 捕获原始环境会更好,但至少在globalenv
中它具有内存效率,并且就像ref的变化一样 .以下是我使用的一些策略 . 我相信.ROW功能可能即将推出 . 以下这些方法都不是很快 . 这些是一些超出子集或过滤的策略 . 我试着像dba一样试图清理数据 . 如上所述,您可以在data.table中选择或删除行:
注意:.SD创建原始数据的子集,并允许您在j或后续data.table中执行相当多的工作 . 见https://stackoverflow.com/a/47406952/305675 . 在这里,我按照Sepal Length命令我的虹膜,将指定的Sepal.Length作为最小值,选择所有物种的前三个(通过Sepal Length)并返回所有伴随数据:
上面的方法在删除行时按顺序重新排序data.table . 您可以转置data.table并删除或替换现在转置列的旧行 . 使用':= NULL'删除转置行时,也会删除后续列名:
将data.frame转置回data.table时,您可能希望在删除的情况下从原始data.table重命名并恢复类属性 . 将“:= NULL”应用于现在转置的data.table会创建所有字符类 .
您可能只想删除可以使用或不使用Key执行的重复行:
也可以使用'.I'添加增量计数器 . 然后,您可以搜索重复的密钥或字段,并通过使用计数器删除记录来删除它们 . 这在计算上很昂贵,但有一些优点,因为您可以打印要删除的行 .
您也可以只用0或NA填充一行,然后使用i查询删除它们: