我有一个这样的字典列表:
[{'points': 50, 'time': '5:00', 'year': 2010},
{'points': 25, 'time': '6:00', 'month':"february"},
{'points':90, 'time': '9:00', 'month': 'january'},
{'points_h1':20, 'month': 'june'}]
我想把它变成一只大熊猫,就像这样:
month points points_h1 time year
0 NaN 50 NaN 5:00 2010
1 february 25 NaN 6:00 NaN
2 january 90 NaN 9:00 NaN
3 june NaN 20 NaN NaN
注意:列的顺序并不重要。
如何将字典列表转换为如上所示的熊猫数据框?
这里的答案在大多数情况下都是正确的,但没有一个能深入了解在不同情况下哪些方法更合适。有关这些方法和其他方法的更多信息,请查看此答案。
假设d是你的口述清单,简单地说:
pd.DataFrame(d)
这也适用于元组列表!
如何使用一个键/值对作为索引(例如时间)?
@卡茨洛夫爵士,你可以在之后再做1[0]
是否可以创建数据帧并在一行中设置索引?
@卡茨洛夫爵士不,这是不可能的转换时,从口述。
至于熊猫0.19.2,文档中没有提到这一点,至少在pandas.DataFrame的文档中没有提到。
@joris它是字典的一部分,使用pd.dataframe(d.set_id('uid',drop=false)
@麦克斯,这是一条线,但不是一个操作(我认为这是卡茨洛夫爵士问题的关键所在)。
在《大熊猫》16.2版中,我必须做pd.DataFrame.from_records(d)才能让它发挥作用。
这种方法的好处在于它还可以与deque一起使用。
使用@joris解决方案时,可以与pandas 0.17.1一起使用
使用0.14.1和@joris'解决方案不起作用,但确实如此
在0.18.1中,如果字典没有相同的键,则必须使用from_records。
How do I convert a list of dictionaries to a pandas DataFrame?
The other answers are correct, but not much has been explained in terms of advantages and limitations of these methods. The aim of this post will be to show examples of these methods under different situations, discuss when to use (and when not to use), and suggest alternatives.
DataFrame(), DataFrame.from_records(), and .from_dict()
Depending on the structure and format of your data, there are situations where either all three methods work, or some work better than others, or some don't work at all.
Consider a very contrived example.
np.random.seed(0)
data = pd.DataFrame(
np.random.choice(10, (3, 4)), columns=list('ABCD')).to_dict('r')
print(data)
[{'A': 5, 'B': 0, 'C': 3, 'D': 3},
{'A': 7, 'B': 9, 'C': 3, 'D': 5},
{'A': 2, 'B': 4, 'C': 7, 'D': 6}]
这个列表由"记录"组成,每个键都存在。这是您可能遇到的最简单的情况。
# The following methods all produce the same output.
pd.DataFrame(data)
pd.DataFrame.from_dict(data)
pd.DataFrame.from_records(data)
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
字典方向词:orient='index'/'columns'。
在继续之前,必须区分不同类型的字典方向,并支持熊猫。主要有两种类型:"列"和"索引"。
orient='columns'具有"列"方向的字典将其键对应于等效数据框中的列。
例如,上面的data位于"列"方向。
data_c = [
{'A': 5, 'B': 0, 'C': 3, 'D': 3},
{'A': 7, 'B': 9, 'C': 3, 'D': 5},
{'A': 2, 'B': 4, 'C': 7, 'D': 6}]
pd.DataFrame.from_dict(data_c, orient='columns')
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
注:如果您使用的是pd.DataFrame.from_records,则方向假定为"列"(您不能另外指定),字典将相应加载。
orient='index'使用这个方向,假设键对应于索引值。这种数据最适合于pd.DataFrame.from_dict。
data_i ={
0: {'A': 5, 'B': 0, 'C': 3, 'D': 3},
1: {'A': 7, 'B': 9, 'C': 3, 'D': 5},
2: {'A': 2, 'B': 4, 'C': 7, 'D': 6}}
pd.DataFrame.from_dict(data_i, orient='index')
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
这种情况在OP中没有考虑,但仍有助于了解。设置自定义索引
如果需要对生成的数据帧进行自定义索引,可以使用index=...参数进行设置。
pd.DataFrame(data, index=['a', 'b', 'c'])
# pd.DataFrame.from_records(data, index=['a', 'b', 'c'])
A B C D
a 5 0 3 3
b 7 9 3 5
c 2 4 7 6
这不受pd.DataFrame.from_dict的支持。处理缺少的键/列
处理缺少键/列值的字典时,所有方法都是现成的。例如,
data2 = [
{'A': 5, 'C': 3, 'D': 3},
{'A': 7, 'B': 9, 'F': 5},
{'B': 4, 'C': 7, 'E': 6}]
# The methods below all produce the same output.
pd.DataFrame(data2)
pd.DataFrame.from_dict(data2)
pd.DataFrame.from_records(data2)
A B C D E F
0 5.0 NaN 3.0 3.0 NaN NaN
1 7.0 9.0 NaN NaN NaN 5.0
2 NaN 4.0 7.0 NaN 6.0 NaN
正在读取列的子集
"如果我不想在每一篇专栏文章中阅读怎么办?"您可以使用columns=...参数轻松地指定此参数。
例如,从上面的data2的示例字典中,如果要只读列"a"、"d"和"f",可以通过传递一个列表来完成:
pd.DataFrame(data2, columns=['A', 'D', 'F'])
# pd.DataFrame.from_records(data2, columns=['A', 'D', 'F'])
A D F
0 5.0 3.0 NaN
1 7.0 NaN 5.0
2 NaN NaN NaN
带有默认方向"列"的pd.DataFrame.from_dict不支持这种情况。
pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
ValueError: cannot use columns parameter with orient='columns'
正在读取行的子集
这些方法都不直接支持。您将不得不迭代您的数据,并在迭代时执行反向删除。例如,要仅从上面的data2中提取第0行和第2行,可以使用:
rows_to_select = {0, 2}
for i in reversed(range(len(data2))):
if i not in rows_to_select:
del data2[i]
pd.DataFrame(data2)
# pd.DataFrame.from_dict(data2)
# pd.DataFrame.from_records(data2)
A B C D E
0 5.0 NaN 3 3.0 NaN
1 NaN 4.0 7 NaN 6.0
解决嵌套数据问题的灵丹妙药:json_normalize。
与上述方法相比,json_normalize函数是一种强有力的、健壮的替代方法,它与字典(记录)列表一起工作,此外还可以处理嵌套字典。
pd.io.json.json_normalize(data)
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
pd.io.json.json_normalize(data2)
A B C D E
0 5.0 NaN 3 3.0 NaN
1 NaN 4.0 7 NaN 6.0
同样,请记住,传递给json_normalize的数据需要采用字典(记录)格式的列表。
如前所述,json_normalize还可以处理嵌套字典。以下是文档中的一个示例。
data_nested = [
{'counties': [{'name': 'Dade', 'population': 12345},
{'name': 'Broward', 'population': 40000},
{'name': 'Palm Beach', 'population': 60000}],
'info': {'governor': 'Rick Scott'},
'shortname': 'FL',
'state': 'Florida'},
{'counties': [{'name': 'Summit', 'population': 1234},
{'name': 'Cuyahoga', 'population': 1337}],
'info': {'governor': 'John Kasich'},
'shortname': 'OH',
'state': 'Ohio'}
]
pd.io.json.json_normalize(data_nested,
record_path='counties',
meta=['state', 'shortname', ['info', 'governor']])
name population state shortname info.governor
0 Dade 12345 Florida FL Rick Scott
1 Broward 40000 Florida FL Rick Scott
2 Palm Beach 60000 Florida FL Rick Scott
3 Summit 1234 Ohio OH John Kasich
4 Cuyahoga 1337 Ohio OH John Kasich
有关meta和record_path参数的更多信息,请查看文档。总结能力
下面是上面讨论的所有方法的表,以及支持的特性/功能。
哇!好吧,这和合并一起,所以post属于API。如果你还没有为大熊猫文件做贡献的话,你应该为这些文件做贡献。特德·佩特罗刚刚在LinkedIn上发表了一篇关于熊猫在Stack Overflow上的流行的文章,并提到缺少好的文档会导致这里的大量问题。
@斯科特伯顿,你说得对,我已经听够了,现在我知道这是我应该认真考虑的事情。我认为文档可以是帮助用户的一个很好的方式,而不仅仅是在只有一小部分相同受众的问题上发布。
这是一个特别有问题的问题,因为哪种方法的细节是好的,哪种情况往往会发生变化,所以有非常冗长、深入的答案,所以不仅不像在大熊猫官方文件中那样有用,而且往往是有害的或误导性的,因为某些功能内部的变化会突然做出答案。不正确或事实错误,并且它与实际的源回购没有明确的联系,无法标记文档更新。
@伊利感谢你的参与,我也同意,因为我看到很多老问题的答案很快就过时了。这一问题尤其突出,因为熊猫API的反复无常……我希望这篇文章符合你的标准;—)
这是一个很好的答案,我认为是时候让我们在最新的熊猫版本下重新讨论那些常见的问题了:—)
@伊利:无论如何,这绝不是不在这里写答案的理由。任何答案都可能过时,这就是我们投票的目的,在这里存在着不同的观点和不同的目标,有不同的方法解释同一件事总是很有价值的。
@我质疑并反对你最后的主张,但总的来说,我同意你的观点。将同一个问题的不同答案汇总在一起并不总是有附加价值的,特别是如果某些答案是基于其他答案的更新或条件差异。在最坏的情况下,当将这些答案整理在一起时,这些答案可能具有破坏性(而不是使用更更新的答案将旧的答案简单地编辑为更正确的状态)。但我还是同意你的观点。
您也可以使用pd.DataFrame.from_dict(d)作为:[cc lang="python"]In [8]: d = [{'points': 50, 'time': '5:00', 'year': 2010},
...: {'points': 25, 'time': '6:00', 'month':"february
问题是如何从dict的列表中构建数据帧,而不是像您在回答中假设的那样从单个dict构建数据帧。
@客人检查更新后的答案。我不是在假设。