【问题标题】:Faster way to add new columns row-by-row onto a large dataframe将新列逐行添加到大型数据框中的更快方法
【发布时间】:2016-10-01 05:08:35
【问题描述】:

我有以下数据框。

> 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]
}

它按预期工作,但处理速度不如预期。

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

【问题讨论】:

    标签: r performance for-loop


    【解决方案1】:

    不是逐行分配,一种选择是从“listofmatrix”中的每个matrices 中提取第一个元素(因为它只有一个列),以返回listvector s,rbind 它并将输出分配给“df”中的新列。

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

    通过在“df”上运行 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
    

    【讨论】:

    • 谢谢,阿克伦。它完美无缺。我对反引号内的[表达不熟悉,你能指教吗?再次感谢您的帮助!
    猜你喜欢
    • 2018-04-09
    • 2020-08-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-22
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多