Vectorization / data.table - 提高12kk记录DF的for循环效率

时间:2017-11-24 07:34:37

标签: r loops data.table vectorization

我需要将该组与20k组相关联,总计达到12M行。

为了解决这个问题,我写了一个for循环,但显然效率很低,我确信这个任务可以很容易地进行矢量化。但是,我正在努力理解如何以矢量化的方式编写这个指令。

问题如下: 我有一个辅助表,有3个功能:ID,start_row,end_Row start_row是my_DF中第一个元素的行索引,属于ID x ;
end_row是my_DF中属于ID x 的最后一个元素的行索引。

矢量化指令应该执行以下操作:

考虑如下的auxiliary_table:

auxiliary_table <- data.frame(ID = c(1,2,3,4), start_row = c(1,4,8,13), end_row = c(3,7,12,14))

考虑如下DF:

  my_df <- data.frame(Var_a = c(1,2,3,1,2,3,4,6,4,3,1,2,1,1)

我们需要根据auxiliary_table中包含的start_row和end_row索引信息关联ID。

solution_df是:

solution_df <- data.frame(my_df, ID=(1,1,1,2,2,2,2,3,3,3,3,3,4,4)

我要求for循环的矢量化,但我打开例如data.table解决方案。

我希望我很清楚并正确地提出我的问题。

1 个答案:

答案 0 :(得分:1)

auxiliary_table是一种游程编码。因此,我建议您使用经过适当转换的inverse.rle()

来尝试auxiliary_table函数

1。 dplyr

library(dplyr)
my_df %>%
  mutate(ID = auxiliary_table %>% 
           transmute(lengths = end_row - start_row + 1L, values = ID) %>% 
           inverse.rle())
   Var_a ID
1      1  1
2      2  1
3      3  1
4      1  2
5      2  2
6      3  2
7      4  2
8      6  3
9      4  3
10     3  3
11     1  3
12     2  3
13     1  4
14     1  4

2。 data.table

这会在不复制ID的情况下添加my_df列。

library(data.table)
setDT(my_df)[, ID := inverse.rle(setDT(auxiliary_table)[
  , .(lengths = end_row - start_row + 1L, values = ID)])][]

根据auxiliary_table的大小,下面的代码可能会更有效率,因为它会将auxiliary_table 转换为

setDT(my_df)[, ID := inverse.rle(setDT(auxiliary_table)[
  , lengths := end_row - start_row + 1L][
    , c("end_row", "start_row") := NULL][
      , setnames(.SD, "ID", "values")])][]