查找经理的经理 ID 的有效方法

Efficient way to find manager's manager's id

我有一个员工数据库,其中包含他们的经理 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)

这里是我写的函数,returns 预期的结果。

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

当我使用 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

我的问题:是否有更有效的方法来获得此结果?目前即使在 10,000 行上 运行 也需要相当长的时间,而我的数据集接近一百万。

我也愿意接受关于更一般问题标题的建议(可能是这个 SQL 问题的一个版本:Most efficient way to find something recursively in a table?

您可以 运行 加入 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

工作原理

联接的语法是 x[i, on=, j]。它使用 ionx 进行子集化,然后对 returns j 进行子集化。这里的关键点是在 i 中设置 id = mgr_id 所以我们要对经理的行进行子集化。

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