将字典列表转换为pandas DataFrame

app*_*ver 550 python dictionary dataframe pandas

我有一个这样的词典列表:

[{'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'}]
Run Code Online (Sandbox Code Playgroud)

我想把它变成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
Run Code Online (Sandbox Code Playgroud)

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

如何将字典列表转换为pandas DataFrame,如上所示?

jor*_*ris 800

假设d是你的dicts列表,只需:

pd.DataFrame(d)
Run Code Online (Sandbox Code Playgroud)

  • @CatsLoveJazz之后你可以做`df = df.set_index('time')` (5认同)
  • 从Pandas 0.19.2开始,文档中没有提到这一点,至少在'pandas.DataFrame'的文档中没有提到这一点. (5认同)
  • 一个人如何使用键/值对之一作为索引(例如时间)? (3认同)
  • 请注意,对于嵌套字典 `'{"":{"...` 您使用 json_normalize 方法,请参阅 @cs95 的详细答案 (3认同)
  • @CatsLoveJazz 不,从 dict 转换时这是不可能的。 (2认同)

cs9*_*s95 86

v0.23 +答案

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


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}]
Run Code Online (Sandbox Code Playgroud)

此列表包含每个键存在的"记录".这是您可能遇到的最简单的情况.

# 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
Run Code Online (Sandbox Code Playgroud)

关于字典方向的单词
在继续之前,重要的是区分不同类型的字典方向,并支持大熊猫.有两种主要类型:"列"和"索引".

orient='index'
具有"列"方向的字典将使其键对应于等效DataFrame中的列.

例如,'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}]
Run Code Online (Sandbox Code Playgroud)

注意:如果您正在使用orient='columns',则假定方向为"列"(您不能另行指定),并且将相应地加载字典.

data
利用该方向,假设键对应于索引值.这种数据最适合pd.DataFrame.from_records.

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
Run Code Online (Sandbox Code Playgroud)

这种情况在OP中没有考虑,但仍然有用.

设置自定义索引
如果需要在结果DataFrame上使用自定义索引,可以使用orient='index'参数进行设置.

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}}
Run Code Online (Sandbox Code Playgroud)

这不受支持pd.DataFrame.from_dict.

处理丢失的键/列
在处理缺少键/列值的字典时,所有方法都可以开箱即用.例如,

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
Run Code Online (Sandbox Code Playgroud)

读取列的子集
"如果我不想阅读每一列,该怎么办?" 您可以使用index=...参数轻松指定此项.

例如,从pd.DataFrame.from_dict上面的示例字典中,如果您只想读取列"A","D"和"F",则可以通过传递列表来实现:

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
Run Code Online (Sandbox Code Playgroud)

columns=...默认的方向"列" 不支持此功能.

data2 = [
     {'A': 5, 'C': 3, 'D': 3},
     {'A': 7, 'B': 9, 'F': 5},
     {'B': 4, 'C': 7, 'E': 6}]
Run Code Online (Sandbox Code Playgroud)

读取行的子集
直接支持任何这些方法.您将不得不迭代数据并在迭代时就地执行反向删除.例如,为了仅提取0 和2 从行data2以上,则可以使用:

# 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
Run Code Online (Sandbox Code Playgroud)

灵丹妙药: pd.DataFrame.from_dict

对上述方法的强大而强大的替代方法是data2与字典列表(记录)一起使用的函数,此外还可以处理嵌套字典.

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
Run Code Online (Sandbox Code Playgroud)

同样,请记住,传递给的数据json_normalize需要采用字典列表(记录)格式.

如前所述,json_normalize还可以处理嵌套的词典.以下是从文档中获取的示例.

pd.DataFrame.from_dict(data2, orient='columns', columns=['A', 'B'])
Run Code Online (Sandbox Code Playgroud)

ValueError: cannot use columns parameter with orient='columns'
Run Code Online (Sandbox Code Playgroud)

有关json_normalizejson_normalize参数的更多信息,请查看文档.


总结

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

在此输入图像描述

  • 哇!好的,这与[合并SO帖子](/sf/answers/3755211841/)属于API.如果你还没有这样做,你应该为熊猫文件做出贡献.Ted Petrou刚刚发布了一篇关于Pandas在Stack Overflow上流行的[LinkedIn文章](https://www.linkedin.com/feed/update/urn:li:activity:6480573916921364480/),并提到缺乏良好的文档有助于这里的问题数量. (4认同)
  • @ScottBoston 你说得对,我已经听过很多次了,我知道这是我应该更认真考虑的事情。我认为文档可以成为帮助用户的一种很好的方式,比发布只会影响一小部分相同受众的问题更重要。 (4认同)
  • @ely:无论如何,这绝不是不写答案*的理由*.**任何**答案都可能过时,这就是我们所投票的,这里存在不同的观点和不同的目标,并且用不同的方式解释同样的事情总是有价值的. (3认同)

sze*_*lin 79

在熊猫16.2中,我必须做到pd.DataFrame.from_records(d)这一点.

  • 在`0.18.1`中,如果字典不具有相同的键,则必须使用`from_records`. (12认同)
  • 与@joris解决方案一起使用pandas`0.17.1`可以正常工作 (3认同)
  • Usinig 0.14.1和@joris的解决方案没有用,但确实如此 (2认同)

shi*_*vsn 19

您还可以使用pd.DataFrame.from_dict(d):

In [8]: d = [{'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'}]

In [12]: pd.DataFrame.from_dict(d)
Out[12]: 
      month  points  points_h1  time    year
0       NaN    50.0        NaN  5:00  2010.0
1  february    25.0        NaN  6:00     NaN
2   january    90.0        NaN  9:00     NaN
3      june     NaN       20.0   NaN     NaN
Run Code Online (Sandbox Code Playgroud)