在数据框中循环遍历行

8
假设我需要以某种方式循环遍历数据框中的行。
我创建了一个简单的数据框。
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())

你知道为什么吗?它们是否使用完全相同的内存量?


3
第一个函数只使用了一次 $,而第二个函数使用了1e6(一百万)次。$ 不是最快的子集选择函数。 - Roland
让我惊讶的是,f1 的速度是 f3 <- function(v)for(a in v){NULL}; system.time(f3(df$id)) 的两倍。哦,我明白了:1e6 不是向量的完整长度。system.time(f3(df$id[1:1e6])) 很快。 - Frank
2个回答

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 

3
f1中,您可以通过将向量传递给函数来完全绕过数据框。因此,您的代码基本上是“我有一个向量!这是第一个元素。这是第二个元素。这是第三个...”
相比之下,在f2中,您将整个数据框传递给它,然后每次获取单个列的每个元素。因此,您的代码是“我有一个数据框。这是ID列的第一个元素。这是ID列的第二个元素。这是第三个...”
如果您提取简单的数据结构(向量)一次,然后只能使用该结构而不是从较大的对象中重复提取简单结构,那么速度会快得多。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接