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问题的一个版本:在表中递归查找某些东西的最有效方法)的建议持开放态度.)
您可以使用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].它使用i和on子集x然后返回j.这里的关键点是设置id = mgr_id,i所以我们将子集化到经理的行.
分配列的语法是DT[, col_name := value].在这种情况下,该值来自最后一段中解释的连接.