查找经理的经理 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]
。它使用 i
和 on
对 x
进行子集化,然后对 returns j
进行子集化。这里的关键点是在 i
中设置 id = mgr_id
所以我们要对经理的行进行子集化。
分配列的语法是DT[, col_name := value]
。在这种情况下,该值来自上一段中解释的联接。
我有一个员工数据库,其中包含他们的经理 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]
。它使用 i
和 on
对 x
进行子集化,然后对 returns j
进行子集化。这里的关键点是在 i
中设置 id = mgr_id
所以我们要对经理的行进行子集化。
分配列的语法是DT[, col_name := value]
。在这种情况下,该值来自上一段中解释的联接。