在R中,如何快速遍历数据帧的行?

Win*_*ang 30 iteration performance r rows dataframe

假设您有一个包含许多行和多列的数据框.

列有名称.您希望按编号访问行,按名称访问列.

例如,循环遍历行的一种(可能很慢)方法是

for (i in 1:nrow(df)) {
  print(df[i, "column1"])
  # do more things with the data frame...
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是为单独的列(如column1_list = df[["column1"])创建"列表" ,并在一个循环中访问列表.这种方法可能很快,但如果要访问许多列,也会很不方便.

是否有一种快速循环数据帧行的方法?其他一些数据结构是否更适合快速循环?

Joh*_*ohn 15

我想我需要做一个完整的答案,因为我发现评论更难以跟踪,我已经失去了一个评论......有一个例子,nullglob演示了for之间的差异,并且比其他例子更好地应用族函数.当一个人使这个功能非常慢时,就会消耗所有的速度,你就不会发现循环变化之间存在差异.但是当你使函数变得微不足道时,你可以看到循环对事物的影响程度.

我还想补充一点,在其他示例中未探索的apply系列的某些成员具有有趣的性能属性.首先,我将在我的机器上显示nullglob相对结果的复制.

n <- 1e6
system.time(for(i in 1:n) sinI[i] <- sin(i))
  user  system elapsed 
 5.721   0.028   5.712 

lapply runs much faster for the same result
system.time(sinI <- lapply(1:n,sin))
   user  system elapsed 
  1.353   0.012   1.361 
Run Code Online (Sandbox Code Playgroud)

他还发现sapply慢得多.以下是一些未经测试的其他产品.

普通旧版适用于矩阵版数据...

mat <- matrix(1:n,ncol =1),1,sin)
system.time(sinI <- apply(mat,1,sin))
   user  system elapsed 
  8.478   0.116   8.531 
Run Code Online (Sandbox Code Playgroud)

因此,apply()命令本身比for循环慢得多.(如果我使用sin(mat [i,1]),for循环不会明显减慢.

另一个似乎没有在其他帖子中测试的是tapply.

system.time(sinI <- tapply(1:n, 1:n, sin))
   user  system elapsed 
 12.908   0.266  13.589 
Run Code Online (Sandbox Code Playgroud)

当然,人们永远不会以这种方式使用tapply,并且在大多数情况下它的效用远远超出任何这样的速度问题.


Sha*_*ane 12

最快的方法是不循环(即矢量化操作).您需要循环的唯一实例之一是存在依赖关系时(即一次迭代依赖于另一次迭代).否则,尝试尽可能多地在循环外进行矢量化计算.

如果你确实需要循环,那么使用for循环基本上和其他任何东西一样快(lapply可以快一点,但其他apply函数往往与速度大致相同for).

  • 也许没有办法避免我想做的事情的循环——请参阅我对上面格雷格评论的回应。 (2认同)
  • “大约相同的速度”?你读了所有的答案吗?在我的回答中,我表明使用 vapply 比 for 循环快 3 倍(例如)... (2认同)
  • 在算法效率方面,它们在速度上非常相似:[算法效率](http://en.wikipedia.org/wiki/Algorithmic_efficiency) (2认同)