更快地将新列逐行添加到大型数据框中

时间:2016-10-01 05:08:35

标签: r performance for-loop

我有以下数据框。

> str(df)
'data.frame':   98444 obs. of  25 variables:
 $ count       : int  361 362 363 364 365 366 367 368 369 370 ...
 $ time        : num  3.01 3.02 3.02 3.03 3.04 ...
 $ H_Rx        : num  -164 -164 -164 -164 -164 ...
 $ H_Ry        : num  -10.7 -10.7 -10.7 -10.7 -10.7 ...
 $ H_Rz        : num  -174 -174 -174 -174 -174 ...
 $ H_Tx        : num  -0.00137 -0.00137 -0.00136 -0.00135 -0.00134 ...
 $ H_Ty        : num  1.67 1.67 1.67 1.67 1.67 ...
 $ H_Tz        : num  -0.194 -0.194 -0.194 -0.194 -0.194 ...
 $ C_Rx        : num  -13.4 -13.4 -13.5 -13.5 -13.6 ...
 $ C_Ry        : num  -14.7 -14.6 -14.5 -14.4 -14.4 ...
 $ C_Rz        : num  7.7 7.69 7.69 7.68 7.67 ...
 $ C_Tx        : num  0.00914 0.00914 0.00914 0.00914 0.00914 ...
 $ C_Ty        : num  1.21 1.21 1.21 1.21 1.21 ...
 $ C_Tz        : num  -0.0466 -0.0466 -0.0466 -0.0465 -0.0465 ...
 $ D_Rx        : num  -32.6 -32.6 -32.6 -32.6 -32.6 ...
 $ D_Ry        : num  -49 -49 -49 -49 -49 ...
 $ D_Rz        : num  1.91 1.91 1.91 1.92 1.92 ...
 $ D_Tx        : num  -0.0403 -0.0403 -0.0403 -0.0402 -0.0402 ...
 $ D_Ty        : num  1.63 1.63 1.63 1.63 1.63 ...
 $ D_Tz        : num  0.0214 0.0214 0.0214 0.0214 0.0215 ...
 $ part        : chr  "P2" "P2" "P2" "P2" ...
 $ freq        : chr  "100Hz" "100Hz" "100Hz" "100Hz" ...
 $ device      : chr  "A1" "A1" "A1" "A1" ...
 $ act         : chr  "Nod" "Nod" "Nod" "Nod" ...
 $ trial       : chr  "Rest" "Rest" "Rest" "Rest" ...
 - attr(*, "na.action")=Class 'omit'  Named int [1:133] 469 470 471 472 473 474 475 476 477 478 ...
  .. ..- attr(*, "names")= chr [1:133] "469" "470" "471" "472" ...

我还有一个矩阵列表。

> str(listofmatrix)
List of 98444
 $ : num [1:4, 1] 0.0807 0.0165 -0.2062 1
 $ : num [1:4, 1] 0.0807 0.0165 -0.2062 1
  [list output truncated]

我从listofmatrix中的每个矩阵中提取了前三个元素,使用for循环将它们放在df中的新列中:

for (i in 1:nrow(df)) {
  df$D_Txnew[i] <- listofmatrix[[i]][1, 1]
  df$D_Tynew[i] <- listofmatrix[[i]][2, 1]
  df$D_Tznew[i] <- listofmatrix[[i]][3, 1]
}

它按预期工作,但处理速度低于理想值。

加快速度的不同方法是什么?

1 个答案:

答案 0 :(得分:2)

不是逐行分配,而是选择从matric es中的每一个中提取第一个元素&lt; listofmatrix&#39; (因为它只有一列)可以返回list vectorrbind,并将输出分配给&#39; df&#39;中的新列。

df1[paste0("D_T", c("xnew", "ynew", "znew"))] <-  do.call(rbind, 
                     lapply(listofmatrix, `[`, 1:3))

在&#39; df&#39;

上运行OP的代码
identical(df, df1)
#[1] TRUE

基准

以下是一些略大的数据集的基准测试

set.seed(142)
listofmatrix <- lapply(1:1e4, function(i) matrix(rnorm(4), ncol=1))
df <- data.frame(count = 1:1e4, act= sample(LETTERS, 1e4, replace=TRUE))
df1 <- df

system.time({
for (i in 1:nrow(df)) {
  df$D_Txnew[i] <- listofmatrix[[i]][1, 1]
  df$D_Tynew[i] <- listofmatrix[[i]][2, 1]
  df$D_Tznew[i] <- listofmatrix[[i]][3, 1]
}
})

#user  system elapsed 
#  1.94    0.00    1.94 
system.time({
df1[paste0("D_T", c("xnew", "ynew", "znew"))] <-  do.call(rbind, 
                     lapply(listofmatrix, `[`, 1:3))
})
# user  system elapsed 
#   0.02    0.00    0.02 

数据

set.seed(24)
listofmatrix <- lapply(1:5, function(i) matrix(rnorm(4), ncol=1))
df <- data.frame(count = 1:5, act= LETTERS[1:5]) 
df1 <- df