DataFrame()
、DataFrame.from_records()
和 .from_dict()
根据数据的结构和格式,有些情况下所有三种方法都适用,有些情况下某些方法比其他方法更好,有些情况下某些方法根本不起作用。
考虑一个非常复杂的例子:
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 |
---|---|---|---|
5 | 0 | 3 | 3 |
7 | 9 | 3 | 5 |
2 | 4 | 7 | 6 |
关于字典方向:orient=‘index’/‘columns’
在继续之前,重要的是要区分不同的字典方向类型,并了解 pandas 的支持情况。有两种主要类型:“columns”和“index”。
orient='columns'
具有“columns”方向的字典将它们的键对应到等效 DataFrame 中的列。
例如,上面的 data
处于“columns”方向。
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 |
---|---|---|---|
5 | 0 | 3 | 3 |
7 | 9 | 3 | 5 |
2 | 4 | 7 | 6 |
注意:如果你使用 pd.DataFrame.from_records
,则默认方向为“columns”(你不能指定其他方式),并且字典将相应地加载。
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 |
---|---|---|---|
5 | 0 | 3 | 3 |
7 | 9 | 3 | 5 |
2 | 4 | 7 | 6 |
这种情况在原始问题中没有考虑,但仍然很有用。
设置自定义索引
如果你需要在生成的 DataFrame 上设置自定义索引,可以使用 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 |
b | 7 | 9 | 3 |
c | 2 | 4 | 7 |
这不受 pd.DataFrame.from_dict
支持。
处理缺失的键/列
所有方法都可以开箱即用地处理带有缺失键/列值的字典。例如,
data2 = [
{'A': 5, 'C': 3, 'D': 3},
{'A': 7, 'B': 9, 'F': 5},
{'B': 4, 'C': 7, 'E': 6}]
以下方法都会产生相同的输出:
pd.DataFrame(data2)
pd.DataFrame.from_dict(data2)
pd.DataFrame.from_records(data2)
A | B | C | D | E | F |
---|---|---|---|---|---|
5.0 | NaN | 3.0 | 3.0 | NaN | NaN |
7.0 | 9.0 | NaN | NaN | NaN | 5.0 |
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 |
---|---|---|
5.0 | 3.0 | NaN |
7.0 | NaN | 5.0 |
NaN | NaN | NaN |
这不受默认 orient='columns'
的 pd.DataFrame.from_dict
支持。
pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
ValueError:无法在 orient='columns'
下使用 columns
参数。
万能解决方案:json_normalize
用于嵌套数据**
一种强大且稳健的替代上述方法的方式是使用 json_normalize
函数,该函数可以处理字典列表(记录),并且还可以处理嵌套字典。
pd.json_normalize(data)
A | B | C | D |
---|---|---|---|
0 | 5 | 0 | 3 |
1 | 7 | 9 | 3 |
2 | 2 | 4 | 7 |
pd.json_normalize(data2)
A | B | C | D | E |
---|---|---|---|---|
0 | 5.0 | NaN | 3 | 3.0 |
1 | NaN | 4.0 | 7 | NaN |
再次提醒,传递给 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 |
---|---|---|---|---|
Dade | 12345 | Florida | FL | Rick Scott |
Broward | 40000 | Florida | FL | Rick Scott |
Palm Beach | 60000 | Florida | FL | Rick Scott |
Summit | 1234 | Ohio | OH | John Kasich |
Cuyahoga | 1337 | Ohio | OH | John Kasich |
有关 meta
和 record_path
参数的更多信息,请参阅相关文档。