Estoy buscando algún consejo sobre cómo convertir limpiamente un diccionario anidado de varios niveles de Python (de JSON) en una tabla booleana de marco de datos.
Normas:
Entrada de ejemplo:
{1:{'group_a':{'bool_a':True, 'bool_b':True, 'bool_n':True}, 'group_n':{'bool_b':True, 'bool_n':True} }, 2:{'group_a':{'bool_a':True, 'bool_b':True, 'bool_n':True}, 'group_n':{'bool_b':True, 'bool_n':True} }, 'n':{'group_a':{'bool_a':True, 'bool_c':True}, 'group_n':{'bool_b':True} }, }Salida deseada:
Ga_Ba, Ga_Bb, Ga_Bc, Ga_Bn, Gn_Ba, Gn_Bb, ... Gn_Bn.... 1 True True False True False True True 2 True True False True False True True n True False True False False False False ...¿Ideas? Puntos de bonificación por velocidad y concisión. Tengo una solución, pero estoy buscando algo más elegante que el lío de bucles for que tengo ahora. Las estructuras de datos alternativas también pueden ser bienvenidas.
s = pd.DataFrame.from_dict(data, orient='index').stack() pd.json_normalize(s).set_index(s.index) \ .stack().unstack([1, 2], fill_value=False) \ .sort_index(axis=1) group_a group_n bool_a bool_b bool_c bool_n bool_b bool_n 1 True True False True True True 2 True True False True True True 3 True False True False True False pd.DataFrame.from_dict({ k0: { f'G{k1.split("_")[1]}_B{k2.split("_")[1]}': val for k1, d1 in d0.items() for k2, val in d1.items() } for k0, d0 in data.items() }, orient='index').fillna(False) Ga_Ba Ga_Bb Ga_Bn Gn_Bb Gn_Bn Ga_Bc 1 True True True True True False 2 True True True True True False 3 True False False True False TruePodrías usar una comprensión de diccionario y concat :
import pandas as pd values = { "1": { "group_a": {"bool_a": True, "bool_b": True, "bool_n": True}, "group_n": {"bool_b": True, "bool_n": True}, }, "2": { "group_a": {"bool_a": True, "bool_b": True, "bool_n": True}, "group_n": {"bool_b": True, "bool_n": True}, }, "n": {"group_a": {"bool_a": True, "bool_c": True}, "group_n": {"bool_b": True}}, } stacked_values = {k: pd.DataFrame(v).stack() for k, v in values.items()} df = ( pd.concat(stacked_values, axis=1) .T.fillna(False) .swaplevel(axis=1) # optional .sort_index(axis=1) )Producción:
group_a group_n bool_a bool_b bool_c bool_n bool_b bool_n 1 True True False True True True 2 True True False True True True n True False True False True Falseintente usar un dataframe pivot_table
dct={1:{'group_a':{'bool_a':True, 'bool_b':True, 'bool_n':True}, 'group_n':{'bool_b':True, 'bool_n':True} }, 2:{'group_a':{'bool_a':True, 'bool_b':True, 'bool_n':True}, 'group_n':{'bool_b':True, 'bool_n':True} }, 'n':{'group_a':{'bool_a':True, 'bool_c':True}, 'group_n':{'bool_b':True} }, } df=pd.DataFrame.from_dict(dct, orient='index') df=df.stack() lst=[] for k,vals in df.items(): for index,item in vals.items(): lst.append((k[0],k[1],index,item)) df=pd.DataFrame(lst,columns=['col1','col2','col3','col4']) #print(df) fp=df.pivot_table(index='col1',columns=['col2','col3'],values='col4', aggfunc=np.any).fillna(False) print(fp)producción:
col2 group_a group_n col3 bool_a bool_b bool_c bool_n bool_b bool_n col1 1 True True False True True True 2 True True False True True True n True False True False True False