从带有列表的字典创建Pandas DataFrame

29

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

当我把这个字典传递给pd.DataFrame尝试将其转换为pandas DataFrame时,它会抛出“Arrays must be the same length”错误。这是因为它无法处理具有多个值的键(即具有列表值的键)。

如何让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']

你事先知道数据的结构吗? - AbtPst
1
一般来说,是的。在这个假设的例子中,“building”始终是一个字符串,“DC?”始终是一个布尔值。但“occupants”列表的长度可能会根据查询的建筑物而变化。这回答了你的问题吗? - Conway
正确,所以我在想,先创建一个空数据框,然后不断向其中添加行。但是需要注意的是,正如Andy指出的那样,这可能是低效的。 - AbtPst
6个回答

34

如果您传递一个行列表,这将起作用:

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]

1
这个解决方案也适用于列表嵌套列表和列表嵌套字典的情况。data = {'building': '白宫', 'DC?': True, 'occupants': ['巴拉克', '米歇尔', '萨莎', '玛丽亚'], 'list_of_lists': [[1, 2, 3], [4, 5, 6]], 'list_of_dicts': [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}]} - Alexander
对我来说没有起作用,因为我有三个列表,每个字典键都有相同的长度。nutrients_totals_dict = { "Name" : cnf_nutrient_names_all, "Value": ["0" for i in range(num_values)], "Units": cnf_nutrient_units_all } - mLstudent33

6
这最终证明是非常琐碎的。
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行为已经发生了变化。 - BenP
嗨@ChinmayKanchi,如果有多行这样的数据,例如第二个房子还有另一个名字x多个的列表怎么办? - Xavier Sun

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

1

如果不是将所有居住者列在一个条目中,而是每个居住者都有单独的条目,这样是否可以接受?如果可以的话,您只需要执行以下操作:

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

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


0

我曾经遇到过一个相关的问题,但是我的数据结构是一个多级字典,其中第二级字典中包含列表:

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。


-1
如果您事先知道字典的键,为什么不先创建一个空数据框,然后再逐行添加呢?

2
这不是很高效的做法,因为每次插入时pandas都会创建一份新副本(因此以这种方式构建DataFrame的时间复杂度在行数上是O(n^2))。 - Andy Hayden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接