- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
函数set
或:=
中的表达式[.data.table
允许用户通过引用更新data.tables。此行为与将操作结果重新分配给原始data.frame有何不同?
keepcols<-function(DF,cols){
eval.parent(substitute(DF<-DF[,cols,with=FALSE]))
}
keeprows<-function(DF,i){
eval.parent(substitute(DF<-DF[i,]))
}
<-
中的RHS是R的最新版本中初始数据帧的浅拷贝,因此这些函数似乎非常有效。这个基本的R方法与data.table等效方法有何不同?差异仅与速度有关,还是与内存使用有关?何时差异最大?
library(data.table)
# Long dataset
N=1e7; K=100
DT <- data.table(
id1 = sample(sprintf("id%03d",1:K), N, TRUE),
v1 = sample(5, N, TRUE)
)
system.time(DT[,a_inplace:=mean(v1)])
user system elapsed
0.060 0.013 0.077
system.time(DT[,a_inplace:=NULL])
user system elapsed
0.044 0.010 0.060
system.time(DT <- DT[,c(.SD,a_usual=mean(v1)),.SDcols=names(DT)])
user system elapsed
0.132 0.025 0.161
system.time(DT <- DT[,list(id1,v1)])
user system elapsed
0.124 0.026 0.153
# Wide dataset
N=1e7; K=100
DT <- data.table(
id1 = sample(sprintf("id%03d",1:K), N, TRUE),
id2 = sample(sprintf("id%03d",1:K), N, TRUE),
id3 = sample(sprintf("id%010d",1:(N/K)), N, TRUE),
v1 = sample(5, N, TRUE),
v2 = sample(1e6, N, TRUE),
v3 = sample(round(runif(100,max=100),4), N, TRUE)
)
system.time(DT[,a_inplace:=mean(v1)])
user system elapsed
0.057 0.014 0.089
system.time(DT[,a_inplace:=NULL])
user system elapsed
0.038 0.009 0.061
system.time(DT <- DT[,c(.SD,a_usual=mean(v1)),.SDcols=names(DT)])
user system elapsed
2.483 0.146 2.602
system.time(DT <- DT[,list(id1,id2,id3,v1,v2,v3)])
user system elapsed
1.143 0.088 1.220
最佳答案
在data.table
中,:=
和所有set*
函数通过引用更新对象。这是在2012年IIRC左右推出的。并且此时,基数R不是浅拷贝,而是深表复制。从3.1.0开始引入浅拷贝。
这是一个冗长的回答,但我认为这回答了您的前两个问题:
这个基本的R方法与data.table等效方法有何不同?差异仅与速度有关,还是与内存使用有关?
在基本R v3.1.0 +中,当我们这样做时:
DF1 = data.frame(x=1:5, y=6:10, z=11:15)
DF2 = DF1[, c("x", "y")]
DF3 = transform(DF2, y = ifelse(y>=8L, 1L, y))
DF4 = transform(DF2, y = 2L)
DF1
到DF2
,两列均仅浅拷贝。 DF2
到DF3
,仅必须复制/重新分配y
列,但是x
再次浅拷贝。 DF2
到DF4
,与(2)相同。 data.table
中,我们就地修改。即使在
DF3
和
DF4
列中,
y
的含义也不会被复制。
DT2[y >= 8L, y := 1L] ## (a)
DT2[, y := 2L]
y
已经是一个整数列,并且我们通过引用对其进行了整数修改,所以这里根本没有新的内存分配。
data.table
中真正喜欢的便捷功能。
numeric
类型(例如
character
类型)时:
DT[, (cols) := lapply(.SD, as.numeric), .SDcols = cols]
DF[] = lapply(DF, as.numeric)
DF
。这意味着,如果您有10列,每行包含1亿个字符类型,那么
DF
将占用以下空间:
10 * 100e6 * 4 / 1024^3 = ~ 3.7GB
numeric
类型的大小是原来的两倍,因此,我们总共需要
7.4GB + 3.7GB
空间,以便我们使用基数R进行转换。
data.table
在
DF1
期间复制到
DF2
。那是:
DT2 = DT1[, c("x", "y")]
DT1
的联接来更新诸如data.table DT2
的列时,可以通过以下方式完成:DT1[DT2, col := i.val]
i.
是val
的DT2
列(i
参数)中用于匹配行的值。该语法允许非常高效地执行此操作,而不必首先联接整个结果,然后更新所需的列。 关于r - “update by reference”与浅拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49759483/
免责声明 这篇文章是关于术语“浅拷贝”和“深拷贝”的正确用法,特别是在谈论复制一个不包含任何引用的对象时。这个问题并不意味着(也不应该)基于意见,除非真的没有关于这个话题的共识。我已将此问题标记为 C
我有这个功能 int getrelation(string name, RELATION& output){ bool found=0; int index=0;
与 why should I make a copy of a data frame in pandas 有关 我注意到在流行的backtesting图书馆, def __init__(self, d
我的问题很基础,但我想 100% 理解所有内容。 SO中的很多问题都引用了我的帖子,但我没有找到满意的答案。 我们知道java中的枚举是引用类型。让我们考虑以下片段: public static cl
请引用这个 fiddle 的问题。 http://jsfiddle.net/AQR55/ 1)为什么附加到隔离范围属性的 watch - 双向绑定(bind)到父属性,不会在更改父范围属性时触发。 在
我想使用 UP3 来完成一项非常具体的任务,我应该能够使用 API 来实现该任务。我想了解是否可以编写以下应用程序。 基于https://jawbone.com/support/articles/00
如何在辅助方法中传递上下文并提取数据? 请参阅以下代码片段: import AppContext from '../../context/AppContext' import extractDatta
我正在尝试使用 simple-git 创建浅克隆。我正在尝试创建与此命令等效的命令:git clone --depth 1 https://github.com/steveukx/git-js.git
我是一名优秀的程序员,十分优秀!