Как распарсить список словарей в столбце датафрейма и получить новый датафрейм?

К вопросу прикладываю пример с синтетическими данными.

import random
import datetime as dt
import pandas as pd

data = {}
for _ in range(9):
    col = {}
    new_key = 'ORD' + '-' + str(random.randint(1, 25))
    col[new_key] = {'Items': [{'item_id': random.randint(1000, 5000), 'price': round(random.uniform(500.01, 1000.01), 2)} for _ in range(3)]}
    data.update(col)
df = pd.DataFrame(data).T.reset_index().rename(columns={'index':'OrderID'})
df['Date'] = pd.date_range(start='2022-01-01', periods=df.shape[0])

Вопрос, как распарсить столбец Items, чтобы получилась плоская таблица, гранулированная до уровня конкретного айтема (OderID и Date должны повторяться, для каждого айтема, относящегося к этому заказу)?

И задачка со звездочкой: как это сделать с помощью json_normalize?


Ответы (1 шт):

Автор решения: strawdog

Попробуйте сделать так:

res = df.explode("Items").loc[:,"Items"].apply(pd.Series).join(df["OrderID"])

res:

    item_id   price OrderID
0    4035.0  999.82   ORD-2
0    2291.0  736.43   ORD-2
0    3503.0  511.94   ORD-2
1    2694.0  704.35  ORD-12
1    1003.0  675.17  ORD-12
1    3308.0  833.18  ORD-12
2    3236.0  867.64  ORD-10
2    1306.0  504.75  ORD-10
2    2675.0  509.90  ORD-10
..      ...     ...     ...
4    3237.0  789.66  ORD-21
4    3336.0  806.11  ORD-21
4    4240.0  888.53  ORD-21
5    2017.0  845.91   ORD-4
5    4837.0  571.32   ORD-4
5    2534.0  929.79   ORD-4
6    3704.0  970.65   ORD-5
6    3925.0  738.19   ORD-5
6    4026.0  982.88   ORD-5


[21 rows x 3 columns]

UPDATE

Можно сделать и с помощью json_normalize, однако не уверен в эффективности этого метода для всего датафрейма, им удобнее работать с сериями:

res = pd.json_normalize(df["Items"]).unstack().apply(pd.Series).droplevel(level=0).join(df["OrderID"])
→ Ссылка