找到经理经理身份的有效方法

BLT*_*BLT 6 performance r mapply

我有一个员工数据库,其中包含经理的ID,长格式(每个员工每月一行).我想添加一个包含其经理的经理ID(或他们的跳过级别经理的ID)的列.

这是一个玩具数据集:

id <- c(seq.int(1,11), seq.int(2,12))
mgr_id <- as.integer(c(NA, 1, 1, 2, 2, 2, 2, 3, 3, 5, 5,   #period 1
                      NA, 2, 5, 2, 5, 5, 3, 3, 5, 10, 10)) #period 2
period <- c(rep(1, 11), rep(2, 11))
left_company <- c(1, rep(0, 21))
joined_company <- c(rep(0, 21), 1) 

df <- data.frame(id, mgr_id, period, left_company, joined_company)
Run Code Online (Sandbox Code Playgroud)

这是我写的一个函数,它返回预期的结果.

# finds the employee's manager in the correct period, and returns that manager's id

    get_mgr_mgr_id <- function(manager_id, period){
      mgr_mgr_id <- df$mgr_id[df$id == manager_id & df$period == period] 
      return(mgr_mgr_id[1])
    }
Run Code Online (Sandbox Code Playgroud)

当我使用该功能时mapply,一切都很好.请注意,员工1离开了公司,他们被员工5取代,员工5被员工10取代,员工12被新员工替换.

df$mgr_mgr_id <- mapply(get_mgr_mgr_id, df$mgr_id, df$period)

df
   id mgr_id period left joined mgr_mgr_id
1   1     NA      1    1      0         NA
2   2      1      1    0      0         NA
3   3      1      1    0      0         NA
4   4      2      1    0      0          1
5   5      2      1    0      0          1
6   6      2      1    0      0          1
7   7      2      1    0      0          1
8   8      3      1    0      0          1
9   9      3      1    0      0          1
10 10      5      1    0      0          2
11 11      5      1    0      0          2
12  2     NA      2    0      0         NA
13  3      2      2    0      0         NA
14  4      5      2    0      0          2
15  5      2      2    0      0         NA
16  6      5      2    0      0          2
17  7      5      2    0      0          2
18  8      3      2    0      0          2
19  9      3      2    0      0          2
20 10      5      2    0      0          2
21 11     10      2    0      0          5
22 12     10      2    0      1          5
Run Code Online (Sandbox Code Playgroud)

我的问题:是否有更有效的方法来获得这个结果?目前,甚至在10,000行上运行需要相当长的时间,而我的数据集已接近一百万.

我也对更一般的问题标题(可能是这个SQL问题的一个版本:在表中递归查找某些东西的最有效方法)的建议持开放态度.)

Fra*_*ank 5

您可以使用data.table运行联接.我不确定会有多快:

library(data.table)
setDT(df)

df[, m2id := df[.(id = mgr_id, period = period), on=c("id", "period"), mgr_id]]

    id mgr_id period left_company joined_company m2id
 1:  1     NA      1            1              0   NA
 2:  2      1      1            0              0   NA
 3:  3      1      1            0              0   NA
 4:  4      2      1            0              0    1
 5:  5      2      1            0              0    1
 6:  6      2      1            0              0    1
 7:  7      2      1            0              0    1
 8:  8      3      1            0              0    1
 9:  9      3      1            0              0    1
10: 10      5      1            0              0    2
11: 11      5      1            0              0    2
12:  2     NA      2            0              0   NA
13:  3      2      2            0              0   NA
14:  4      5      2            0              0    2
15:  5      2      2            0              0   NA
16:  6      5      2            0              0    2
17:  7      5      2            0              0    2
18:  8      3      2            0              0    2
19:  9      3      2            0              0    2
20: 10      5      2            0              0    2
21: 11     10      2            0              0    5
22: 12     10      2            0              1    5
    id mgr_id period left_company joined_company m2id
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

连接的语法是x[i, on=, j].它使用ion子集x然后返回j.这里的关键点是设置id = mgr_id,i所以我们将子集化到经理的行.

分配列的语法是DT[, col_name := value].在这种情况下,该值来自最后一段中解释的连接.

  • 我的解决方案花了> 5分钟,10000行.@Frank的回答耗时约为1,000,000.所以+1,但是对于某些(不相关的?)原因,输出并不总是在我的实际数据上一直都是正确的.我正在研究为什么会这样. (2认同)