【问题标题】:Python: How to create nested Dictionary from tuples?Python:如何从元组创建嵌套字典?
【发布时间】:2021-11-01 05:30:56
【问题描述】:

我认为这个问题与本论坛之前的问题类似。但是,我仍然对如何从元组列表创建嵌套字典有疑问。

假设我有以下元组:

my_list = [
 ('actor', 'actor_id', 'integer', 'NO'),
 ('actor', 'first_name', 'character varying', 'NO'),
 ('actor_info', 'actor_id', 'integer', 'YES'),
 ('actor_info', 'first_name', 'character varying', 'YES')]

# convert into DataFrame
col = ['table', 'col_name', 'dtype', 'isnull']
df = pd.DataFrame(mylist, columns=col)

print(df)

        table     col_name                        dtype   isnull
0       actor     actor_id                      integer     NO
1       actor   first_name            character varying     NO
2  actor_info     actor_id                      integer    YES
3  actor_info   first_name            character varying    YES

当前结果:

{
 'actor': {
    'actor_id': {'dtype': 'integer', 'isnull': 'NO'},
    'first_name': {'dtype': 'character varying', 'isnull': 'NO'}
    },
 'actor_info': {
    'actor_id': {'dtype': 'integer', 'isnull': 'YES'},
    'first_name': {'dtype': 'character varying', 'isnull': 'YES'}
    }
}

预期结果(应按表名分组):

{
 'actor': 
    [
        {'column': 'actor_id', 'dtype': 'integer', 'isnull': 'NO'},
        {'column': 'first_name', 'dtype': 'character varying', 'isnull': 'NO'}
    ],
 'actor_info': 
    [
        {'column': 'actor_id', 'dtype': 'integer', 'isnull': 'YES'},
        {'column': 'first_name', 'dtype': 'character varying', 'isnull': 'YES'}
    ]
}

我尝试通过将 my_list 转换为 DataFrame 来制作嵌套字典。但是,我无法获得所需的输出结果。这是我的当前代码

# convert to nested dictionary
ff = df.iloc.groupby(['table'])[['col_name','dtype','isnull']].apply(lambda x: x.set_index('col_name').to_dict(orient='index')).to_dict()

# convert to JSON
print(json.dumps(ff, indent=1))

你能帮我解决这种问题吗?

我也很好奇如何转换为DataFrame(例如,列表理解、嵌套循环)来解决这个问题。任何有助于解决此问题的帮助将不胜感激。谢谢

【问题讨论】:

  • 你的输出不清楚,你的意思是应该是table_name -> list of dicts吗?因为显然,您不能在 dict (column) 中有重复键。其次,除非您真的打算使用 pandas 进行进一步操作,否则绝对应该坚持使用纯 Python。似乎有点矫枉过正。
  • @kva1966 哦,对不起。感谢您的指正和建议。我已经编辑了我的问题(预期结果)。
  • 没问题。只是还是有点好奇,要一份清单吗?因为如果您使用大括号 ({}),这意味着字典(在您当前的编辑中)。如果您希望列元数据位于列表中,则应为[ ... ](方括号)。很抱歉吹毛求疵,只是您的预期输出仍然不太正确,将其放入 Ipython 或类似文件中,它会出错,因为字典必须是键值对,所以您有 { val1, val2 }
  • @kva1966 啊,我明白了。是的,我只想返回每列的列元数据。实际上,我在设计输出时有点困惑,我应该将[]{} 作为输出。谢天谢地,你给了我解释。谢谢。

标签: python pandas dictionary


【解决方案1】:

根据我的评论,我假设您需要每个表名的列元数据列表,而不是字典的字典。

如果是这样,这是一种简单的方法。

from collections import defaultdict

d = defaultdict(list)

for tablename, col, dtype, isnull in my_list:
    d[tablename].append({ 'column': col, 'dtype': dtype, 'isnull': isnull })

输出(在 ipython 中):

In [19]: d
Out[19]:
defaultdict(list,
            {'actor': [{'column': 'actor_id',
               'dtype': 'integer',
               'isnull': 'NO'},
              {'column': 'first_name',
               'dtype': 'character varying',
               'isnull': 'NO'}],
             'actor_info': [{'column': 'actor_id',
               'dtype': 'integer',
               'isnull': 'YES'},
              {'column': 'first_name',
               'dtype': 'character varying',
               'isnull': 'YES'}]})

In [20]: d['actor']
Out[20]:
[{'column': 'actor_id', 'dtype': 'integer', 'isnull': 'NO'},
 {'column': 'first_name', 'dtype': 'character varying', 'isnull': 'NO'}]

In [21]: d['actor_info']
Out[21]:
[{'column': 'actor_id', 'dtype': 'integer', 'isnull': 'YES'},
 {'column': 'first_name', 'dtype': 'character varying', 'isnull': 'YES'}]

【讨论】:

  • 感谢您的帮助。非常感谢。
  • 请问@kva1966,我可以根据tablename 对dict d 上的数据进行切片/过滤吗?例如,我想从['actor','actor_info','address'] 获取数据(假设我有超过 3 个表名)。谢谢
  • stackoverflow.com/questions/29216889/… 只是一个一般提示:请在提问之前先搜索,因为这是一个直截了当的问题。其次,充分利用 Stackoverflow 就是要非常具体地提出问题,如果解决了即时查询,则有单独的问题。如果链接中的切片答案不是您想要的,请打开一个新问题,就像您在此处所做的那样,使用示例数据和示例输出。
  • 顺便说一句,如果我的回答解决了你的问题,你能接受它作为你正在寻找的答案吗?如果没有,那就太好了,或者您正在等待更多。
【解决方案2】:

很容易理解字典:

from itertools import groupby

{k: {a: dict(zip(('column', 'dtype', 'isnull'), b])) for _,a,*b in g}
 for k,g in groupby(my_list, lambda t: t[0])}

注意。 groupby 假设初始数组是按分组键排序的,如果不是则需要先排序

输出:

{'actor': {'actor_id': {'column': 'integer', 'dtype': 'NO'},
  'first_name': {'column': 'character varying', 'dtype': 'NO'}},
 'actor_info': {'actor_id': {'column': 'integer', 'dtype': 'YES'},
  'first_name': {'column': 'character varying', 'dtype': 'YES'}}}

【讨论】:

  • 嗨@mozway,感谢您的帮助。非常感激。我尝试了您的解决方案,但它只返回每个项目的最后一个值。例如。表actor 有两个col_nameactor_idfirst_name,它只返回列first_name。你能解释一下吗?
  • 当您可以使用多个分配时,为什么要在此答案中使用切片? {k: dict(zip(('column', 'dtype', 'isnull'), v)) for k, *v in my_list}
  • @furanzup 抱歉,我没有看到嵌套级别,请查看更新的答案
  • @Jab 是的,两者都是可能的,我更新了答案
  • @mozway 哇,谢谢你的回答。非常感谢。
猜你喜欢
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-18
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多