假设由于某种原因,我需要循环数据框中的行。
我创建了一个简单的data.frame
df <- data.frame(id = sample(1e6, 1e7, replace = TRUE))
似乎f2比f1慢得多,而我预计它们是等价的。
f1 <- function(v){
for (obs in 1:(1e6) ){
a <- v[obs]
}
a
}
system.time(f1(df$id))
f2 <- function(){
for (obs in 1:(1e6) ){
a <- df$id[obs]
}
a
}
system.time(f2())
你知道为什么吗?他们使用完全相同的内存量吗?
答案 0 :(得分:7)
如果您改为写下这样的时间并认识到df$x
实际上是一个函数调用(`$`(df,x)
),那么这个谜团就会消失:
system.time(for(i in 1:1e6) df$x)
# user system elapsed
# 8.52 0.00 8.53
system.time(for(i in 1) df$x)
# user system elapsed
# 0 0 0
答案 1 :(得分:3)
在f1
中,只需将向量传递给函数即可完全绕过数据框。所以你的代码基本上是“我有一个向量!这是第一个元素。这是第二个元素。这是第三个......”
相比之下,在f2
中,您给它一个完整的数据框,然后每次获取单个列的每个元素。所以你的代码是“我有一个数据框。这是ID列的第一个元素。这是ID列的第二个元素。这是第三个......”
如果提取一次简单的数据结构(向量),然后只能使用它,而不是从较大的对象中重复提取简单结构,它会快得多。