首页 > 解决方案 > 将 Pandas 数据框中的 JSON 数据转换为数据框本身的最佳方法

问题描述

我有一个 Pandas 数据框,其中一列在每一行中包含一个非嵌套的 json 对象。

                             js
0  {"k1":"1","k2":"A","k3":"X"}
1  {"k1":"2","k2":"B","k3":"X"}
2  {"k1":"3","k2":"A","k3":"Y"}
3  {"k1":"4","k2":"D","k4":"M"}

像这样创建:

import pandas as pd
L0 = ['{"k1":"1","k2":"A","k3":"X"}',
      '{"k1":"2","k2":"B","k3":"X"}',
      '{"k1":"3","k2":"A","k3":"Y"}',
      '{"k1":"4","k2":"D","k4":"M"}']
df = pd.DataFrame({'js':L0})

我想将 json-objects 变成他们自己的数据框:

  k1 k2   k3   k4
0  1  A    X  NaN
1  2  B    X  NaN
2  3  A    Y  NaN
3  4  D  NaN    M

现在我知道的唯一方法是使用json模块和df.iterrows()

import json
all_json = []
for _,row in df.iterrows():
    all_json.append(json.loads(row["js"]))
df2 = pd.DataFrame.from_dict(all_json)

有没有更好的方法来做到这一点,理想情况下不需要迭代?

编辑1:

感谢您的回答。

ast.literal_eval我已经在我自己的方法所采用的真实数据上使用了三种建议的方法158 ms ± 4.01 ms

df = df.apply(lambda x: ast.literal_eval(x[0]), 1).apply(pd.Series)需要640 ms ± 7.8 ms

df['js'].apply(ast.literal_eval).apply(pd.Series)需要636 ms ± 19 ms

pd.DataFrame(df.js.apply(ast.literal_eval).tolist())需要180 ms ± 5.11

正如所建议的,第三种方法是最快的,但遗憾的是它们都比 - 方法慢,iterrows而我的意图是摆脱iterrows它以使其更快。

编辑2: 所以我猜我们有一个赢家pd.DataFrame(df["js"].apply(json.loads).tolist())25.2 ms ± 512 µs

标签: pythonjsonpandasdataframe

解决方案


使用ast.literal_eval和应用pd.Series为:

import ast
df = df.apply(lambda x: ast.literal_eval(x[0]), 1).apply(pd.Series)

print(df)
  k1 k2   k3   k4
0  1  A    X  NaN
1  2  B    X  NaN
2  3  A    Y  NaN
3  4  D  NaN    M

或者:

df = pd.DataFrame([ast.literal_eval(i) for i in df['js']])

或者:

import json
df = pd.DataFrame([json.loads(i) for i in df['js']])

推荐阅读