python json pandas dataframe flatten

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)


cree una función personalizada para aplanar columnB luego use pd.concat

def flatten(js): return pd.DataFrame(js).set_index(''pos'').squeeze() pd.concat([df.drop([''columnA'', ''columnB''], axis=1), df.columnA.apply(pd.Series), df.columnB.apply(flatten)], axis=1)