我有一个员工数据库,其中包含经理的ID,长格式(每个员工每月一排)。我想添加一个包含其经理的经理ID(或他们的跳过级别经理的ID)的列。
这是一个玩具数据集:
(a -> a) -> a -> a
这是我写的一个返回预期结果的函数。
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)
当我使用# 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])
}
函数时,一切都很好。请注意,员工1离开了公司,他们被员工5取代,员工10被员工10取代,员工12被新员工替换。
mapply
我的问题:是否有更有效的方法来获得此结果?目前,即使在10,000行上运行也需要很长时间,而我的数据集已接近一百万。
我也欢迎就更一般的问题标题提出建议(可能是这个SQL问题的一个版本:Most efficient way to find something recursively in a table?)
答案 0 :(得分: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
工作原理
联接的语法是x[i, on=, j]
。它使用i
和on
来分组x
,然后返回j
。这里的关键点是在id = mgr_id
中设置i
,因此我们将子集化为经理的行。
分配列的语法是DT[, col_name := value]
。在这种情况下,该值来自上一段中解释的连接。