【问题标题】:Transform hierarchy from Excel columns into rows将层次结构从 Excel 列转换为行
【发布时间】:2020-06-10 21:09:10
【问题描述】:

我有 3 列的 Excel:

OrgunitCode    ParentOrgunitCode     OrgunitName

1500                  Nan                 Head_Org

3200                  1500              2nd_level_Org

3201                  1500              other_2nd_lever_Org

..............................................................

971248197              827484           n_level_Org

103048197              513834           n2_level_Org

我需要将其转换为完整的层次结构行(使用 Excel 或 Python):

OrgunitName OrgunitCode    OrgunitName(lvl_2) OrgunitCode(lvl_2) .. OrgunitName(lvl_5) OrgunitCode(lvl_5)

Head_Org        1500        2nd_level_Org          3200                  n_level_Org         971248197 

Head_Org        1500        2nd_level_Org          3200                  n2_level_Org         513834

..............................................................

所以我想在excel中使用数据透视表或查找,但是如果我从“父母”开始搜索,我不知道有多少“孩子”,所以我很困惑。而且我不知道如何从最低点开始,因为如何找到它们

【问题讨论】:

标签: python excel pandas tree hierarchy


【解决方案1】:

哦……与层次结构一起工作的乐趣。总是很有趣。

首先,在处理父子关系时,我总是建议为级别 1 构建一个像“/”这样的组织节点; '/1/', '/2/' ... '/n/' 用于第 2 级; '/1/1', '/2/1/', '/2/2/'... '/n/n/' 用于级别 3 等。这将使您的层次结构工作更容易(如排序,查找不同部门的后代、兄弟姐妹和祖先等)。

在您的情况下,您实际上并不需要组织节点,但我已将其包含在 D 列中以供将来参考:

这假设第 1 行是标题,并且数据组织为:

A: OrgunitCode 
B: ParentOrgunitCode 
C: OrgunitName

然后将这些公式添加到第 2 行:

D: OrgNode (not used but useful in future)
=IF(COUNTIFS($A:$A,B2)=0,"/"&A2&"/",VLOOKUP(B2,$A:$D,4,FALSE)&$A2&"/")

E: Hierarchy level
=IF(COUNTIFS($A:$A,$B2)=0,1,VLOOKUP($B2,$A:$E,5,FALSE)+1)

接下来是您要求的层次结构。将此公式分别粘贴到单元格 E2 和 F2 中,然后拖动它们以覆盖所有相关的行和层次结构级别。

F: OrgunitName
=IF($E2=(COLUMN()-4)/2,$C2,IF($E2<(COLUMN()-4)/2,"",VLOOKUP($B2,$A:F,COLUMN(),FALSE)))

G: OrgunitCode
=IF($E2=(COLUMN()-5)/2,$A2,IF($E2<(COLUMN()-5)/2,"",VLOOKUP($B2,$A:G,COLUMN(),FALSE)))

请注意,在将公式向右扩展时,G 和 F 中的查找列是相对的,以避免更改数字或添加数字行来引用。但是,如果列未完全按照上述方式拆分,您可能必须将“COLUMN()”部分替换为数字或数字引用。

还有一件事:VLOOKUP 在这里可以工作,但请注意,它对 Excel 来说是一个繁重的操作,所以如果你有一个非常大的层次结构,你可能要考虑在 SQL 中使用层次结构函数,在 MySQL 中使用循环函数,或者类似。

剖析公式

编辑:按要求解释公式(我认为这是一团糟,但不知道更好的方法):

D: OrgNode (not used but useful in future)
=IF(COUNTIFS($A:$A,B2)=0,"/"&A2&"/",VLOOKUP(B2,$A:$D,4,FALSE)&$A2&"/")

Builds a hierarchy node with the parent/child relationship seperated by '/':
'COUNTIFS($A:$A,B2)=0'              <- checks to see if there is a parent. 
"/"&A2&"/"                          <- ...If no, then this is the/a top node, so take the OrgCode and wrap it in '/'
VLOOKUP(B2,$A:$D,4,FALSE)&$A2&"/")  <- Else, look up the parent's orgnode and add this department's OrgCode and '/' to the parent's.


E: Hierarchy level
=IF(COUNTIFS($A:$A,$B2)=0,1,VLOOKUP($B2,$A:$E,5,FALSE)+1)

Just determines the hierarchy level of the dept in question.
=IF(COUNTIFS($A:$A,$B2)=0       <- checks to see if there is a parent.
1                               <- if not, then make this hierarchy level 1
VLOOKUP($B2,$A:$E,5,FALSE)+1)   <- Else, lookup the hierarchy level of the parent and add 1

F: OrgunitName
=IF($E2=(COLUMN()-4)/2,$C2,IF($E2<(COLUMN()-4)/2,"",VLOOKUP($B2,$A:F,COLUMN(),FALSE)))

=IF($E2=(COLUMN()-4)/2,     <- checks to see if the current hierarchy column is equal to the hierarchy level of the current department 
$C2                         <- if so, return the dept name
IF($E2<(COLUMN()-4)/2       <- else check if the current hierarchy column is lower than the hierarchy level of the current department
""                          <- if so, remain blank
VLOOKUP($B2,$A:F,COLUMN(),FALSE))) <- else lookup the value in this column of the parent department.

G: OrgunitCode 
=IF($E2=(COLUMN()-5)/2,$A2,IF($E2<(COLUMN()-5)/2,"",VLOOKUP($B2,$A:G,COLUMN(),FALSE)))

- Same explanation as above, just a different column reference and returns department code instead
=IF($E2=(COLUMN()-5)/2
$A2
IF($E2<(COLUMN()-5)/2
""
VLOOKUP($B2,$A:G,COLUMN(),FALSE)))

然后把它雕刻出来:

(COLUMN()-4)/2  <- Instead of hardcoding the hierarhy levels, this uses the column index to calculate the relevant hierarchy level in the given column. Column F is index 6: (6-4)/2 = 1. Column H is index 8: (8-4)/2 = 2. etc.

COLUMN()        <- In the VLOOKUP reference: We all know VLOOKUP is annoying beacause we have to manually change the number in the col_index_num parameter when dragging across columns. But similar to above, we can use the column index number as a relative reference. Hence her, column F is index 6 and will look up the 6th column. Column G will return the 7th, H the 8th... you get the point.

【讨论】:

  • 处理我的数据,谢谢!对于不大的数据库来说,这似乎是一个可靠的解决方案。如果您评论了您的功能,那就太好了,这样会更容易理解它们的工作原理!
  • 你最后一个奴隶是怎么死的? :o)
猜你喜欢
  • 1970-01-01
  • 2022-09-27
  • 2015-05-03
  • 2022-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多