Tengo una lista de diccionario como ese:

my_list = [
    {
        'Currency': 'USD',
        'Product': 'a',
        'Quantity': {
            'Apr 2019': 1.0,
            'Jun 2019': 7.0
        }
    },
    {
        'Currency': 'USD',
        'Product': 'b',
        'Quantity': {
            'Jan 2019': 4.0,
            'Feb 2019': 8.0
        }
    }
]

Y quiero un marco de datos como ese:

 Currency Product Quantity  Date
 'USD'      'a'      1      Apr 2019
 'USD'      'a'      7      Jun 2019
 'USD'      'b'      4      Jan 2019
 'USD'      'b'      8      Feb 2019

Actualmente estoy haciendo eso:

for element in my_list :
     currency = element.get('Currency')
     product = element.get('Product')
     dates = list(element.get('Quantity').keys())
     for date in dates:
         quantity = element.get('Quantity')[date]
         row = [currency, product, quantity, date]
         df.loc[df.shape[0]] = row

Pero me imagino que hay una mejor manera en lugar de bucle en la lista y

pd.DataFrame.from_dict(my_list)

Funciona si solo hay un valor en cantidad (con una pequeña modificación con .apply)

Gracias

2
kilag 7 oct. 2019 a las 18:37

3 respuestas

La mejor respuesta
df_dict = [{**d, "Quantity": quantity, "Date": date,} for d in my_list for date, quantity in d['Quantity'].items()]

df = pd.DataFrame.from_dict(df_dict)

salida :

>>> df

Currency    Product Quantity    Date
0   USD         a       1.0         Apr 2019
1   USD         a       7.0         Jun 2019
2   USD         b       4.0         Jan 2019
3   USD         b       8.0         Feb 2019

Explicación :

Al usar un bucle anidado doble, enumera su lista por el número de pares de cantidad / fecha, que es lo que desea. Luego, desempaqueta el diccionario en el primer nivel (usando **d). Esto establece los valores correctos Currency y Product pero nos deja con el valor "malo" Quantity. Esto se sobrescribe en el siguiente paso de la comprensión del diccionario. Y finalmente, se establece Date. A partir de ahí, simplemente los pandas leen cada diccionario como una fila.

2
Brian Joseph 7 oct. 2019 a las 16:47

Puede usar doble bucle para procesar sus datos.

El siguiente código

df = pd.DataFrame(
    [
        {
            'Currency': item.get('Currency'),
            'Product': item.get('Product'),
            'Date': quant_key,
            'Quantity': quant_val,
        } for item in my_list for quant_key, quant_val in item['Quantity'].items()
    ]
)
print(df)

Devuelve esta salida:

  Currency Product      Date  Quantity
0      USD       a  Apr 2019       1.0
1      USD       a  Jun 2019       7.0
2      USD       b  Jan 2019       4.0
3      USD       b  Feb 2019       8.0
1
Jaroslav Bezděk 7 oct. 2019 a las 16:02

Utilice json_normalize:

from pandas.io.json import json_normalize
df=json_normalize(my_list,'Quantity',['Currency','Product'])
Quantity=[]
for d in my_list:
    for month in  d['Quantity']:
        Quantity.append(d['Quantity'][month])
df['Quantity']=Quantity
df=df.rename(columns={0:'Date'}).reindex(columns=['Currency','Product','Quantity','Date'])
print(df)


  Currency Product  Quantity      Date
0      USD       a       1.0  Apr 2019
1      USD       a       7.0  Jun 2019
2      USD       b       4.0  Jan 2019
3      USD       b       8.0  Feb 2019
1
ansev 7 oct. 2019 a las 15:50
58272841