У меня есть фрейм данных 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-объекты в свой собственный фрейм данных:
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
, чтобы сделать его быстрее.
EDIT 2: pd.DataFrame(df["js"].apply(json.loads).tolist())
берет 25.2 ms ± 512 µs
поэтому у нас есть победитель, я думаю.