我有一个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
使其更快。
编辑2:
pd.DataFrame(df["js"].apply(json.loads).tolist())
花了25.2 ms ± 512 µs
,所以我猜想有一个赢家。
答案 0 :(得分:3)
使用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
OR:
df = pd.DataFrame([ast.literal_eval(i) for i in df['js']])
OR:
import json
df = pd.DataFrame([json.loads(i) for i in df['js']])
答案 1 :(得分:2)
在将字符串转换为dict后,我将调用dataframe构造函数(我认为这样做会更快):
constructor(private db: AngularFirestore) {
this.usersCollection = this.db.collection<User>('Users');
this.users = this.usersCollection.snapshotChanges().pipe(
map(actions => {
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data };
});
})
);
}
或者:
getUser(id) {
this.usersCollection = this.db.collection<User>('Users', ref => ref.where('userId', '==', id));
this.users = this.usersCollection.snapshotChanges().pipe(
map(actions => {
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
return { id, ...data };
});
})
);
return this.users;
}
import ast
pd.DataFrame(df.js.apply(ast.literal_eval).tolist())
答案 2 :(得分:1)
您可以使用apply(pd.Series)
:
import ast
print(df['js'].apply(ast.literal_eval).apply(pd.Series))
输出:
k1 k2 k3 k4
0 1 A X NaN
1 2 B X NaN
2 3 A Y NaN
3 4 D NaN M