Saltar al contenido

¿Cómo aplanar un marco de datos de pandas con algunas columnas como json?

Solución:

Aquí hay una solución usando json_normalize() de nuevo mediante el uso de una función personalizada para obtener los datos en el formato correcto entendido por json_normalize función.

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, únete al DFs en el índice común para obtener:

df[['id', 'name']].join([A, B])

Imagen


EDITAR:- Según 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 el uso ast.literal_eval() si sabe que la fuente de datos es JSON.

El más rápido parece ser:

json_struct = json.loads(df.to_json(orient="records"))    
df_flat = pd.io.json.json_normalize(json_struct) #use pd.io.json

crear una función personalizada para aplanar columnB luego usa 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)

ingrese la descripción de la imagen aquí

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *