在R中递归处理员工和主管数据以生成组织树层级结构

3

我通常使用"组织树"格式分析数据,以了解组织内给定领导下活动的频率。 我需要从两列数据(员工姓名和主管姓名)生成一个宽阔的层次结构。

----------
df <- data.frame("Employee"=c("Bill","James","Amy","Jen","Henry"),
                      "Supervisor"=c("Jen","Jen","Steve","Amy","Amy"))
df
#   Employee Supervisor
# 1     Bill        Jen
# 2    James        Jen
# 3      Amy      Steve
# 4      Jen        Amy
# 5    Henry        Amy

以一个宽数据框的形式结束,该数据框需要指定组织结构图,以CEO(或最高级别员工)开始:
#  Employee       H1     H2    H3
# 1    Bill    Steve    Amy   Jen
# 2   James    Steve    Amy   Jen
# 3     Amy    Steve     NA    NA
# 4     Jen    Steve    Amy    NA
# 5   Henry    Steve    Amy    NA

经过大量的研究,data.tree 包似乎提供了最多的帮助。我该如何执行此操作?

你可以使用 data.tree::FromDataFrameNetwork(df) 来创建一棵树。你确定最终输出中需要这样的列吗?之后你打算如何处理这些数据? - MrFlick
我对最终输出没有特别的要求,你有什么建议吗?我需要一种方法来按给定领导人(例如Amy)进行筛选,并更改数据以代表该领导人的员工(最终向该领导人汇报的任何人)。 - Dale Kube
2个回答

2

试试这个:

library(data.table)
setDT(df)

setnames(df, 'Supervisor', 'Supervisor.1')

j=1
while (df[, any(get(paste0('Supervisor.',j)) %in% Employee)]) {
  df[df, on=paste0('Supervisor.',j,'==Employee'),
     paste0('Supervisor.',j+1):= i.Supervisor.1]
  j = j + 1
}

> df
#    Employee Supervisor.1 Supervisor.2 Supervisor.3
# 1:     Bill          Jen          Amy        Steve
# 2:    James          Jen          Amy        Steve
# 3:      Amy        Steve           NA           NA
# 4:      Jen          Amy        Steve           NA
# 5:    Henry          Amy        Steve           NA

在行内重新排序:

df = cbind(df[, 1], t(apply(df[, -1], 1, function(r) c(rev(r[!is.na(r)]), r[is.na(r)]))))
> df
#    Employee    V1  V2  V3
# 1:     Bill Steve Amy Jen
# 2:    James Steve Amy Jen
# 3:      Amy Steve  NA  NA
# 4:      Jen Steve Amy  NA
# 5:    Henry Steve Amy  NA

在所有情况下,"Steve" 应该是 Supervisor.1,并且层次关系应从左到右。我对 data.table 不熟悉,请您快速调整代码以满足这些要求。 - Dale Kube
@DaleKube,完成了。 - sirallen
这个解决方案不具备良好的可扩展性。例如,如果我使用一个包含1,000条员工ID和主管ID记录的数据框,输出将是一个非常宽的数据框,有1,000列。显然,在组织中并不存在1,000个分层级别。 - Dale Kube
@DaleKube 这更可能是由于层次结构中的不规则性引起的。如果没有看到它,就不能说太多其他的事情了。 - sirallen

1
如果你不坚持要输出结果,而是想要与层次结构一起工作,那么data.tree是一个很好的选择。以下是一些示例:
libary(data.tree)
df <- data.frame("Employee"=c("Bill","James","Amy","Jen","Henry"),
                 "Supervisor"=c("Jen","Jen","Steve","Amy","Amy"))

dt <- FromDataFrameNetwork(df)

#here's your org chart:

print(dt)

让我们一起找到Jenna的下属,以及他们在等级体系中的级别:

Get(FindNode(dt, 'Jen')$leaves, 'level')

这将返回如下内容:
 Bill James 
    4     4 

仅供娱乐,让我们添加人员预算:

dt$Set(salary = c(100000, 80000, 60000, 40000, 35000, 70000))

打印工资和累计工资

print(dt, 'salary', sal_subordinates = function(node) Aggregate(node, 'salary', sum))

这将会打印出如下内容:
          levelName salary sal_subordinates
1 Steve             100000            80000
2  °--Amy            80000           130000
3      ¦--Jen        60000            75000
4      ¦   ¦--Bill   40000            40000
5      ¦   °--James  35000            35000
6      °--Henry      70000            70000

数据树 文献 包含了许多处理分层数据和聚合的示例。


使用data.tree,是否有一种简单的方法将您最后的示例转换回像上面提到的数据框格式? - Dale Kube

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接