将字典列表转换为 pandas DataFrame

新手上路,请多包涵

如何将字典列表转换为 DataFrame ?鉴于:

 [{'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'}]

我想把上面的变成 DataFrame

       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

注意:列的顺序无关紧要。

原文由 appleLover 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 953
2 个回答

如果 dsdict 的列表:

 df = pd.DataFrame(ds)

注意:这不适用于嵌套数据。

原文由 joris 发布,翻译遵循 CC BY-SA 4.0 许可协议

如何将字典列表转换为 pandas DataFrame?

其他答案是正确的,但在这些方法的优点和局限性方面没有太多解释。这篇文章的目的是展示这些方法在不同情况下的示例,讨论何时使用(何时不使用),并提出替代方案。


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}]

该列表由“记录”组成,每个键都存在。这是您可能遇到的最简单的情况。

 # 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'

在继续之前,重要的是要区分不同类型的字典方向,并支持 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

OP 中未考虑这种情况,但了解它仍然有用。

设置自定义索引

如果您需要对生成的 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  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.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

有关 metarecord_path 参数的更多信息,请查看文档。


总结

这是上面讨论的所有方法以及支持的特性/功能的表格。

在此处输入图像描述

\* 使用 orient='columns' 然后转置以获得与 orient='index' 相同的效果。

原文由 cs95 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题