python - ¿Cómo aplanar un marco de datos pandas con algunas columnas como json?
dataframe flatten (3)
Aquí hay una solución que usa json_normalize()
nuevamente usando una función personalizada para obtener los datos en el formato correcto entendido por la función json_normalize
.
import ast
from pandas.io.json import json_normalize
def only_dict(d):
''''''
Convert json string representation of dictionary to a python dict
''''''
return ast.literal_eval(d)
def list_of_dicts(ld):
''''''
Create a mapping of the tuples formed after
converting json strings of list to a python list
''''''
return dict([(list(d.values())[1], list(d.values())[0]) for d in ast.literal_eval(ld)])
A = json_normalize(df[''columnA''].apply(only_dict).tolist()).add_prefix(''columnA.'')
B = json_normalize(df[''columnB''].apply(list_of_dicts).tolist()).add_prefix(''columnB.pos.'')
Finalmente, únase a los DFs
en el índice común para obtener:
df[[''id'', ''name'']].join([A, B])
EDITAR: - De acuerdo con el comentario de @MartijnPieters, la forma recomendada de decodificar las cadenas json sería usar json.loads()
que es mucho más rápido en comparación con usar ast.literal_eval()
si sabe que la fuente de datos es JSON .
Tengo un df
drama de datos que carga datos de una base de datos. La mayoría de las columnas son cadenas json, mientras que algunas son incluso listas de jsons. Por ejemplo:
id name columnA columnB
1 John {"dist": "600", "time": "0:12.10"} [{"pos": "1st", "value": "500"},{"pos": "2nd", "value": "300"},{"pos": "3rd", "value": "200"}, {"pos": "total", "value": "1000"}]
2 Mike {"dist": "600"} [{"pos": "1st", "value": "500"},{"pos": "2nd", "value": "300"},{"pos": "total", "value": "800"}]
...
Como puede ver, no todas las filas tienen el mismo número de elementos en las cadenas json para una columna.
Lo que tengo que hacer es mantener las columnas normales como id
y name
tal como están y aplanar las columnas json de esta manera:
id name columnA.dist columnA.time columnB.pos.1st columnB.pos.2nd columnB.pos.3rd columnB.pos.total
1 John 600 0:12.10 500 300 200 1000
2 Mark 600 NaN 500 300 Nan 800
He intentado usar json_normalize
así:
from pandas.io.json import json_normalize
json_normalize(df)
Pero parece que hay algunos problemas con keyerror
. ¿Cuál es la forma correcta de hacer esto?
Lo más rápido parece ser:
json_struct = json.loads(df.to_json(orient="records"))
df_flat = pf.io.json.json_normalize(json_struct)