【问题标题】:Setup up a hierarchy from dicts从字典设置层次结构
【发布时间】:2018-12-20 15:25:58
【问题描述】:

我有一个员工的 CSV 文件,其中包含员工数据,包括姓名、老板、部门 ID 和部门名称。 通过读取该 CSV 文件,我创建了这两个 dict 结构:

dep = {}
dep[1] = {'name': 'Sales', 'parent': None}
dep[2] = {'name': 'National Sales', 'parent': None}
dep[3] = {'name': 'International Sales', 'parent': None}
dep[4] = {'name': 'IT', 'parent': None}
dep[5] = {'name': 'Development', 'parent': None}
dep[6] = {'name': 'Support', 'parent': None}
dep[7] = {'name': 'Helpdesk', 'parent': None}
dep[8] = {'name': 'Desktop support', 'parent': None}
dep[9] = {'name': 'CEO', 'parent': None}

emp = {}
emp[1] = {'name': 'John', 'boss': None, 'dep': 9}
emp[2] = {'name': 'Jane', 'boss': 1, 'dep': 1}
emp[3] = {'name': 'Bob', 'boss': 2, 'dep': 1}
emp[4] = {'name': 'Clara', 'boss': 2, 'dep': 2}
emp[5] = {'name': 'George', 'boss': 3, 'dep': 2}
emp[6] = {'name': 'Steve', 'boss': 2, 'dep': 3}
emp[7] = {'name': 'Joe', 'boss': 1, 'dep': 4}
emp[8] = {'name': 'Peter', 'boss': 7, 'dep': 5}
emp[9] = {'name': 'Silvia', 'boss': 7, 'dep': 6}
emp[10] = {'name': 'Mike', 'boss': 9, 'dep': 7}
emp[11] = {'name': 'Lukas', 'boss': 10, 'dep': 7}
emp[12] = {'name': 'Attila', 'boss': 7, 'dep': 8}
emp[13] = {'name': 'Eva', 'boss': 12, 'dep': 8}

除此之外,我有 2 个任务:

  1. 创建部门层次结构。 (基本上填充的值 父键)
  2. 显示(列出)老板的所有部门和员工

第 2 点的预期结果是(每个从事销售工作的人):

employees = {1: (2, 3, 4, 5, 6)}

对于在全国销售部门工作的每个人:

employees = {4: (5)}

对于在国际销售部门工作的每个人(史蒂夫是唯一一个,没有人为他工作)):

employees = {6: None}

如何以高效的方式实现这一点(我必须处理数千名员工)?

编辑: 这是一个(简化的)CSV 文件结构:

id;name;boss;dep_id;dep_name
    1;John;;9;CEO
    2;Jane;1;1;Sales
    3;Bob;2;1;Sales
    4;Clara;2;2;National Sales
    5;George;3;2;National Sales
    6;Steve;2;3;International Sales
    7;Joe;1;4;IT
    8;Peter;7;5;Development
    9;Silvia;7;6;Support
    10;Mike;9;7;Helpdesk
    11;Lukas;10;7;Helpdesk
    12;Attila;7;8;Desktop support
    13;Eva;12;8;Desktop support

【问题讨论】:

  • 1.缺少信息,例如,上级部门存储在哪里。 2. 当您的键是整数范围时,字典可能是错误的结构,请考虑结构列表或 pandas 数据框。 3. 你试过什么?你遇到了什么具体问题。 4. 如果是一次性操作,真的需要高性能吗?
  • 没有遗漏信息。我必须从员工 CSV 平面文件中构建部门结构。创建部门层次结构的唯一方法是由老板(部门领导是老板与实际员工不在同一部门工作的人
  • @kmac:根据 2:一个字典,如果恕我直言,它的结构正确,因为它为每个键创建一个且只有一个条目。根据 3:我被卡住了。当然,我可以通过每次迭代的整个结构,但我正在寻找一种更快(更优雅)的解决方案。根据 4:我有数千个并发用户。我每天多次从人力资源部门收到此文件。当我正在构建这个结构时(并且在检查是否应该更新数据库之后)这个信息对用户不可用。所以它必须是高性能的。
  • 你必须使用字典吗?因为数据框可能是更好的方法......
  • @Helena:不,字典不是必须的,但我想如果我使用 DF,问题会完全相同。 (而且我更熟悉 dicts 并且 dict 在后台使用的资源更少)

标签: python dictionary hierarchy


【解决方案1】:

正如 cmets 中所建议的,这里有一个使用 pandas 的解决方案。该文件是使用您的示例数据模拟的,对于几千个条目来说应该足够快。

from StringIO import StringIO
import pandas as pd

f = StringIO("""
id;name;boss;dep_id;dep_name
1;John;1;9;CEO
2;Jane;1;1;Sales
3;Bob;2;1;Sales
4;Clara;2;2;National Sales
5;George;3;2;National Sales
6;Steve;2;3;International Sales
7;Joe;1;4;IT
8;Peter;7;5;Development
9;Silvia;7;6;Support
10;Mike;9;7;Helpdesk
11;Lukas;10;7;Helpdesk
12;Attila;7;8;Desktop support
13;Eva;12;8;Desktop support
""")

# load data
employees = pd.read_csv(f, sep=';', index_col=0)

### print a department ###
# Filter by department and print the names
print employees[employees.dep_id == 7].name

### build org hierarchy ###
# keep only one entry per department (assumes they share a boss)
org = employees[['boss', 'dep_id']].drop_duplicates('dep_id')
# follow the boss id to their department id
# note: the CEO is his own boss, to avoid special casing
org['parent'] = org.dep_id.loc[org['boss']].values
# reindex by department id, and keep only the parent column
# note: the index is like your dictionary key, access is optimized
org = org.set_index('dep_id')[['parent']]
print org

【讨论】:

  • 虽然这似乎回答了我的问题,但使用 pandas 使我的生活变得更加复杂(它将 NaN 值解释为浮点数,字符串值解释为 int,不剥离 char 值, ETC。)。如果我想指定所需的数据类型,我总是会收到 TypeError: data type not understand 错误消息。而且由于存在数据类型不匹配,我无法与来自数据库的数据进行比较(即我不知道是否应该更新以及应该更新什么,等等......)。因此,如果您只有数字数据,pandas 很好,但只要您有复杂的数据类型,它就会变得非常复杂。
  • 是的,pandas 添加了一些约束以在某些任务中表现出色。数据以 csv 格式输入的事实很好地暗示了 pandas 是正确的选择(它擅长表格数据)。 csv 解析器允许您指定数据类型并添加自定义 NaN 处理,但另一种选择是预处理 csv 以转换有问题的字段。元数据/版本控制可以在数据表本身之外完成。
  • 事实上,pandas 给我的限制远多于帮助。而且文档,至少对我来说是不够的/直截了当的(即没有描述 read_csv 接受什么样的 dtype,因为 str 不是其中之一。等等)。就像上面提到的字符串的“数据类型不理解”或“整数列有 NA 值”类型的错误。所以仅仅读取一个简单的,主要是基于 str 的 CSV 文件有太多的魔力。所以最后我最终使用了计划字典(实际上是 8 个,因为主文件包含 7 个其他主数据表的数据),执行数据库插入/更新/删除任务
猜你喜欢
  • 2016-05-06
  • 1970-01-01
  • 2023-03-19
  • 2011-06-27
  • 1970-01-01
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
  • 2016-06-27
相关资源
最近更新 更多