【问题标题】:Pandas DataFrame from Dictionary with Lists带有列表的字典中的 Pandas DataFrame
【发布时间】:2016-02-03 22:02:50
【问题描述】:

我有一个 API,它以 Python 字典的形式返回单行数据。大多数键都有一个值,但有些键的值是列表(甚至是列表列表或字典列表)。

当我将字典放入 pd.DataFrame 以尝试将其转换为 pandas DataFrame 时,它​​会引发“数组必须是相同长度”的错误。这是因为它无法处理具有多个值的键(即具有列表值的键)。

如何让 pandas 将列表视为“单值”?

作为一个假设的例子:

data = { 'building': 'White House', 'DC?': True,
         'occupants': ['Barack', 'Michelle', 'Sasha', 'Malia'] }

我想把它变成这样的DataFrame:

ix   building         DC?      occupants
0    'White House'    True     ['Barack', 'Michelle', 'Sasha', 'Malia']

【问题讨论】:

  • 你事先知道传入的数据的结构吗?
  • 一般来说,是的。在假设的例子中,“building”总是一个字符串,而“DC?”将始终是一个布尔值。但是“住户”列表的长度可能会根据所查询的建筑物而变化。这能回答你的问题吗?
  • 正确,所以我在想,先创建一个空白数据框,然后继续向其中添加行。但是,请注意,正如 Andy 指出的那样,这可能效率低下

标签: python pandas


【解决方案1】:

我有一个密切相关的问题,但我的数据结构是一个多级字典,二级字典中有列表:

result = {'hamster': {'confidence': 1, 'ids': ['id1', 'id2']},
          'zombie': {'confidence': 1, 'ids': ['id3']}}

当使用pd.DataFrame([result]) 导入它时,我最终会得到名为hamsterzombie 的列。 (对我来说)正确的导入是将这些作为行标题,并将 confidenceids 作为列标题。为此,我使用了pd.DataFrame.from_dict

In [42]: pd.DataFrame.from_dict(result, orient="index")
Out[42]:
         confidence         ids
hamster           1  [id1, id2]
zombie            1       [id3]

这适用于 python 3.8 + pandas 1.2.3。

【讨论】:

    【解决方案2】:

    从列表字典中创建数据框的解决方案,其中键成为排序索引并提供列名。适合从抓取的 html 表中创建数据框。

    d = { 'B':[10,11], 'A':[20,21] }
    df = pd.DataFrame(d.values(),columns=['C1','C2'],index=d.keys()).sort_index()
    df
    
        C1  C2
    A   20  21
    B   10  11
    

    【讨论】:

      【解决方案3】:

      这最终证明是非常微不足道的

      data = { 'building': 'White House', 'DC?': True, 'occupants': ['Barack', 'Michelle', 'Sasha', 'Malia'] }
      df = pandas.DataFrame([data])
      print df
      

      结果:

          DC?     building                         occupants
      0  True  White House  [Barack, Michelle, Sasha, Malia]
      

      【讨论】:

      • 这适用于 python 3.x。 pandas from_dict 的行为似乎发生了变化。
      • 嗨@ChinmayKanchi,如果有不止一行这样的数据怎么办,例如。像第二个房子还有另一个 [names x multiple] 列表?
      【解决方案4】:

      如果您没有一个包含居住者列表的条目,而是为每个居住者提供单独的条目,这是否可以接受?如果是这样,你可以这样做

      n = len(data['occupants'])
      for key, val in data.items():
          if key != 'occupants':
              data[key] = n*[val]
      

      编辑:实际上,即使没有这种预处理,我也会在 pandas 中得到这种行为(即仅使用 pd.DataFrame(data))。你用的是什么版本?

      【讨论】:

        【解决方案5】:

        如果您传递一个(行)列表,这将有效:

        In [11]: pd.DataFrame(data)
        Out[11]:
            DC?     building occupants
        0  True  White House    Barack
        1  True  White House  Michelle
        2  True  White House     Sasha
        3  True  White House     Malia
        
        In [12]: pd.DataFrame([data])
        Out[12]:
            DC?     building                         occupants
        0  True  White House  [Barack, Michelle, Sasha, Malia]
        

        【讨论】:

        • 此解决方案也适用于列表列表和字典列表。 data = { 'building': 'White House', 'DC?': True, 'occupants': ['Barack', 'Michelle', 'Sasha', 'Malia'] , 'list_of_lists': [[1,2,3], [4,5,6]], 'list_of_dicts': [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}]}
        • 它对我不起作用,因为每个字典键都有 3 个相同长度的列表。nutrients_totals_dict = { "Name" : cnf_nutrient_names_all, "Value": ["0" for i in range(num_values)], "Units": cnf_nutrient_units_all }
        【解决方案6】:

        如果你事先知道字典的键,为什么不先创建一个空数据框,然后继续添加行呢?

        【讨论】:

        • 这不是很有效,因为 pandas 会为每次插入创建一个新副本(因此以这种方式构建 DataFrame 的行数为 O(n^2))。
        猜你喜欢
        • 2023-04-02
        • 2016-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-18
        • 2018-05-30
        • 2016-07-24
        • 1970-01-01
        相关资源
        最近更新 更多