python - 将 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
解决方案
使用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']])
推荐阅读
- javascript - 如何拆分每个单词和空格?
- laravel - 如何从关系中获取随机数据和groupby?
- django - 无法通过子进程从 app/views.py 运行 manage.py 命令
- php - 迁移问题:无法在laravel中添加外键约束
- multithreading - 缓存一致性:线程与核心
- javascript - vue 路由器无法读取未定义的属性“推送”
- php - 在PHP中逐列读取rpt文件内容
- three.js - TypeError:无法读取未定义的属性“旋转”-three.js
- c# - DataGrid 隐藏 DataRows 滚动条不反映可见数据行
- c - 如何使用 gtk3 在 linux 上的 c 中的窗口之间切换