如何将一个字典列表转换为pandas DataFrame?
其他答案是正确的,但在这些方法的优点和限制方面没有做太多解释。本文的目的是展示这些方法在不同情况下的示例,讨论何时使用(以及何时不使用),并提出替代方案。
根据数据的结构和格式,有些情况下这三种方法都适用,有些情况下某些方法比其他方法更好,有些情况下某些方法根本不适用。
考虑一个非常牵强的例子。
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}]
这个列表包含了每个键都存在的“记录”,这是您可能遇到的最简单的情况。
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'
在继续之前,需要明确区分不同类型的词典方向,并了解 pandas 的支持。主要有两种类型:“列”和“行”。
orient='columns'
“列”方向的词典将其键值对应于等效 DataFrame 中的列。
例如,上面的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
虽然这种情况在原始问题中没有被考虑,但了解它仍然很有用。
设置自定义索引
如果您需要在结果DataFrame上设置自定义索引,可以使用index=...
参数进行设置。
pd.DataFrame(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
使用默认的 orient 参数 "columns",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)
A B C D E
0 5.0 NaN 3 3.0 NaN
1 NaN 4.0 7 NaN 6.0
json_normalize
函数是一个强大、健壮的替代方法,适用于字典(记录)列表,并且还可以处理嵌套字典。
pd.json_normalize(data)
A B C D
0 5 0 3 3
1 7 9 3 5
2 2 4 7 6
pd.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.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
参数的更多信息,请查阅文档。
总结
以下是上面讨论的所有方法的表格,以及支持的特性/功能。
![enter image description here](https://istack.dev59.com/SRbw9.webp)
* 使用 orient='columns'
然后转置即可获得与 orient='index'
相同的效果。
df = df.set_index('time')
жқҘи®ҫзҪ®зҙўеј•дёәж—¶й—ҙгҖӮ - jorispandas.DataFrame
的文档中没有。 - Leo Alekseyev'{"":{"...
,您需要使用json_normalize
方法进行规范化处理,详见@cs95的详细回答。 - questionto42