r语言 - 为什么我需要将 data.table 分配给新对象来过滤行?



我刚刚开始学习 data.table 在 r 和

library(data.table)
data(iris)
iris[Species == 'setosa']

上面的代码不会过滤数据集中物种为 setosa 的行,它只是打印满足条件的行。

iris <- iris[Species == 'setosa']

上面的代码有效,但我想知道我需要在什么样的情况下分配一个新对象才能使操作有效,而不仅仅是打印结果。另外,在同一对象上分配是否有任何风险?

从根本上说,列在 R 中更容易修改按引用,因为列是列表元素,并且列表元素不会连续存储在内存中。

通过引用删除列仅意味着取消分配其分配的内存并删除关联的指针

相比之下,删除一些行要困难得多,并且不能真正通过引用来完成 - 一些复制是不可避免的。考虑一个包含两列(AB(的表的简化表示:

1  2  3  4  5
A: [ ][ ][ ][ ][ ]
B: [ ][ ][ ][ ][ ]

A作为大小为5*sizeof(A)的数组存储在连续内存中。 例如,如果A是一个integer,则每个单元格有4个字节。numeric为每个单元格 8 个字节。

从内存的角度来看,删除B很容易:只需告诉R/您的系统您不再需要该内存:

1  2  3  4  5
A: [ ][ ][ ][ ][ ]
B: [x][x][x][x][x]

A的内存分配不受影响。

相比之下,请考虑从表中删除一些行(即AB(:

1  2  3  4  5
A: [ ][x][x][ ][ ]
B: [ ][x][x][ ][ ]

如果我们简单地释放这 4 个单元格的内存,我们的表将被破坏——它的组成内存已被拆分为第 1 行和第 4 行之间的2*sizeof(A)大小间隙。

我们能做的最好的事情就是尝试通过移动第 4 行和第 5 行来最小化复制,并保留第 1 行:

1  2  3<-4<-5
A: [ ][x][x][ ][ ]
B: [ ][x][x][ ][ ]
1  4  5
A: [ ][ ][ ]
B: [ ][ ][ ]

在链接的答案中,Matt 提到了一个非常特殊的情况,其中按引用方法可以工作——当要添加/删除的行位于末尾时。希望插图清楚地说明为什么这更容易做到。

这种技术难度是链接功能请求如此难以满足的原因。如图所示复制许多列的数据说起来容易做起来难,需要很多技巧才能使其正常工作并从 C 正确传达回 R。

最新更新