【问题标题】:Change a column containing list of dict to columns in a DataFrame将包含 dict 列表的列更改为 DataFrame 中的列
【发布时间】:2022-01-25 23:35:18
【问题描述】:

我有以下 DataFrame,其中包含一列是 dict 项列表:

    d = pd.DataFrame([
        ['Green', [{'Desc:': 'STERLING GREEN SO'}, {'Sec:': '01'}, {'Lot:': 'L0038'}, {'Block:': 'B0008'}]],
        ['Apply', [{'Desc:': 'STERLING GREEN SO'}, {'Sec:': '01'}, {'Lot:': 'L0038'}, {'Block:': 'B0008'}]],
        ['Range', [{'Desc:': 'STERLING GREEN SO'}, {'Sec:': '01'}, {'Lot:': 'L0038'}, {'Block:': 'B0008'}]],
        ['Peop',  [{'Desc:': 'STERLING GREEN SO'}, {'Sec:': '01'}, {'Lot:': 'L0038'}, {'Block:': 'B0008'}]]
        ], columns=['Name', 'Legal Description'])

我想将它转换为一个简单的 DataFrame,如下所示:

    d = pd.DataFrame([
        ['Green', 'STERLING GREEN SO', '01', 'L0038', 'B0008'],
        ['Apply', 'STERLING GREEN SO', '01', 'L0038', 'B0008'],
        ['Range', 'STERLING GREEN SO', '01', 'L0038', 'B0008'],
        ['Peop',  'STERLING GREEN SO', '01', 'L0038', 'B0008']
        ], columns=['Name', 'Legal Description', 'Desc', 'Sec', 'Lot', 'Block'])

【问题讨论】:

    标签: python pandas dictionary


    【解决方案1】:

    IMO,理想的解决方案是在上游采取行动并获得格式正确的字典或数据框。

    您的单键字典列表的问题是您必须合并它们。您可以为此使用字典理解并转换为系列:

    d2 = d['Legal Description'].apply(lambda c:
                                      pd.Series({next(iter(x.keys())).strip(':'):
                                                 next(iter(x.values())) for x in c})
                                      )
    

    然后加入原始数据框:

    d.drop(columns='Legal Description').join(d2)
    

    输出:

        Name               Desc Sec    Lot  Block
    0  Green  STERLING GREEN SO  01  L0038  B0008
    1  Apply  STERLING GREEN SO  01  L0038  B0008
    2  Range  STERLING GREEN SO  01  L0038  B0008
    3   Peop  STERLING GREEN SO  01  L0038  B0008
    

    【讨论】:

    • 这非常快速和优雅! 2个问题,我对源代码有一点控制,对于这个例子,一个格式正确的字典会是什么样子?更重要的是,我在哪里可以知道你做了什么!
    • 1-运行d.drop(columns='Legal Description').join(d2).to_dict('list'),这将为您提供一个很好的格式来提供给pd.DataFrame。 2- 很难告诉你,在哪里并不多,在我看来,最重要的是编写代码,尝试解决问题并改进你所做的事情。在这个网站上阅读很多精选的论坛/书籍/好的答案,并保持批判性思维;)
    【解决方案2】:

    如果可能,您应该在创建 DataFrame 之前整理您的数据。它比创建后重塑 DataFrame 更快。例如,像

    data = [
        ['Green', [{'Desc:': 'STERLING GREEN SO'}, {'Sec:': '01'}, {'Lot:': 'L0038'}, {'Block:': 'B0008'}]],
        ['Apply', [{'Desc:': 'STERLING GREEN SO'}, {'Sec:': '01'}, {'Lot:': 'L0038'}, {'Block:': 'B0008'}]],
        ['Range', [{'Desc:': 'STERLING GREEN SO'}, {'Sec:': '01'}, {'Lot:': 'L0038'}, {'Block:': 'B0008'}]],
        ['Peop',  [{'Desc:': 'STERLING GREEN SO'}, {'Sec:': '01'}, {'Lot:': 'L0038'}, {'Block:': 'B0008'}]]
    ]
    
    records = []
    
    for name, legal_desc in data:
        rec = {'Name': name}
        rec.update(x for d in legal_desc for x in d.items())
        records.append(rec)
        
    d = pd.DataFrame(records)
    

    输出:

    >>> d
    
        Name              Desc: Sec:   Lot: Block:
    0  Green  STERLING GREEN SO   01  L0038  B0008
    1  Apply  STERLING GREEN SO   01  L0038  B0008
    2  Range  STERLING GREEN SO   01  L0038  B0008
    3   Peop  STERLING GREEN SO   01  L0038  B0008
    
    >>> records 
    
    [{'Name': 'Green', 'Desc:': 'STERLING GREEN SO', 'Sec:': '01', 'Lot:': 'L0038', 'Block:': 'B0008'}, {'Name': 'Apply', 'Desc:': 'STERLING GREEN SO', 'Sec:': '01', 'Lot:': 'L0038', 'Block:': 'B0008'}, {'Name': 'Range', 'Desc:': 'STERLING GREEN SO', 'Sec:': '01', 'Lot:': 'L0038', 'Block:': 'B0008'}, {'Name': 'Peop', 'Desc:': 'STERLING GREEN SO', 'Sec:': '01', 'Lot:': 'L0038', 'Block:': 'B0008'}]
    

    【讨论】:

    • 之前没见过语法“name, legal_desc = row”,它是干什么的,在哪里可以用?这与“for name, legal_desc in data”相比如何?
    • @QuentinJS 如果您了解for name, legal_desc in data 的作用,那么您就了解name, legal_desc = row 的语法。原理相同,称为可迭代解包。每个row 是一个包含两个元素的列表,赋值只是将元素解包并分配给不同的变量,但实际上,你的建议更好,我会编辑答案。
    【解决方案3】:

    你也可以使用:

    df.set_index('Name', inplace=True)
    df =  df['Legal Description'].explode().apply(pd.Series).groupby(level=0).sum().reset_index()
    

    OUTPUT

        Name              Desc: Sec:   Lot: Block:
    0  Apply  STERLING GREEN SO   01  L0038  B0008
    1  Green  STERLING GREEN SO   01  L0038  B0008
    2   Peop  STERLING GREEN SO   01  L0038  B0008
    3  Range  STERLING GREEN SO   01  L0038  B0008
    

    【讨论】:

      猜你喜欢
      • 2018-12-03
      • 2018-10-14
      • 2021-12-03
      • 2018-02-23
      • 2021-10-06
      • 1970-01-01
      • 2022-10-13
      • 2018-10-12
      • 2018-12-11
      相关资源
      最近更新 更多