【问题标题】:Why I need to assign a data.table to a new object to filter rows?为什么我需要将 data.table 分配给新对象以过滤行?
【发布时间】:2019-12-26 15:06:05
【问题描述】:

我刚刚开始学习 r 中的 data.table 和

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

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

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

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

【问题讨论】:

标签: r data.table


【解决方案1】:

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

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

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

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

A 作为大小为5*sizeof(A) 的数组存储在连续内存中。例如。如果Ainteger,则每个单元格分配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 个单元格的内存,我们的表格将会被破坏 - 它的组成内存已被分割,其第一行和第四行之间存在2*sizeof(A)-size 间隙。

我们能做的最好的就是尝试通过移动第 4 行和第 5 行并保留第 1 行来尽量减少复制:

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

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

linked answer 中,Matt 提到了一个非常具体的情况,在这种情况下,按引用的方法可以工作——当要添加/删除的行出现在末尾时。希望插图能清楚说明为什么这样做更容易。

这个技术难题是linked feature request 如此难以填写的原因。如图所示复制许多列的数据说起来容易做起来难,需要很多技巧才能使其正常工作并从 C 正确地传回 R。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    • 2015-07-31
    • 2016-02-10
    相关资源
    最近更新 更多