簡體   English   中英

Pandas dataframe 到字典列表

[英]Pandas dataframe to list of dicts

我有 Dataframe ,如下所示。 它包含有關計划、活動和項目的信息。 每個計划包含多個活動,每個活動包含多個項目。

| plan_id | plan_name | activity_id | activity_name | item_id | item_name |
| --------| --------- |------------ |-------------- |-------- |---------- |
| 1       | plan1     | 1           | activity1     | 1       | item1     |
| 1       | plan1     | 2           | activity2     | 3       | item3     |
| 2       | plan2     | 1           | activity1     | 1       | item1     |

我想將其轉換為字典列表

[
    {
        'plan_id':1,
        'plan_name':plan1,
        activities:
        [
            {
                activity_id: 1,
                activity_name: 'activity1'
                items:
                [
                    {
                        'item_id:1,
                        'item_name':'item1'
                    }
                ]
            },
            {
                activity_id: 2,
                activity_name: 'activity2'
                items:
                [
                    {
                        'item_id:3,
                        'item_name':'item3'
                    }
                ]
            }
        ]
    },
    {
        'plan_id':2,
        'plan_name':plan2,
        activities:
        [
            {
                activity_id: 1,
                activity_name: 'activity1'
                items:
                [
                    {
                        'item_id:1,
                        'item_name':'item1'
                    }
                ]
            }
        ]
    }
]

有什么快速的方法可以做到這一點嗎?

更新

我發現一種解決方案是創建 3 個數據框 - 包含項目、活動和計划,並像這樣循環它們:

plans_dict = plans_df.to_dict('records')
for plan in plans_dict:
    plan['activities'] = activities_df[activities_df['id']==plan['id']].to_dict('records')
    for activity in plan['activities']:
        activity['items'] = items_df[items_df['activity_id']==activity['activity_id']].to_dict('records')

我不確定這是否是最快的解決方案。 還有其他想法嗎?

這個怎么樣:

def group_dict(df, name, keys):
    gkeys = [k for k in df.columns if k not in keys]
    r = df.groupby(gkeys)[keys].apply(pd.DataFrame.to_dict, orient='records')
    return r.to_frame(name).reset_index()

def to_grouped_dicts(df):
    df1 = group_dict(df, 'items', ['item_id', 'item_name'])
    df2 = group_dict(df1, 'activities', ['activity_id', 'activity_name', 'items'])
    return df2.to_dict(orient='records')

然后:

>>> to_grouped_dicts(df)
[{'plan_id': 1,
  'plan_name': 'plan1',
  'activities': [{'activity_id': 1,
    'activity_name': 'activity1',
    'items': [{'item_id': 1, 'item_name': 'item1'}]},
   {'activity_id': 2,
    'activity_name': 'activity2',
    'items': [{'item_id': 3, 'item_name': 'item3'}]}]},
 {'plan_id': 2,
  'plan_name': 'plan2',
  'activities': [{'activity_id': 1,
    'activity_name': 'activity1',
    'items': [{'item_id': 1, 'item_name': 'item1'}]}]}]

解釋

這個想法是收集給定組的字典列表。 例如,第一行:

df1 = group_dict(df, 'items', ['item_id', 'item_name'])

做一個df.groupby('plan_id', 'plan_name', 'activity_id', 'activity_name') ; 對於每個這樣的組,它會查看所需的鍵( ['item_id', 'item_name'] )並將包含該內容的字典列表放入一個名為'items'的新列中:

print(df1)
   plan_id plan_name  activity_id activity_name  \
0        1     plan1            1     activity1   
1        1     plan1            2     activity2   
2        2     plan2            1     activity1   

                                    items  
0  [{'item_id': 1, 'item_name': 'item1'}]  
1  [{'item_id': 3, 'item_name': 'item3'}]  
2  [{'item_id': 1, 'item_name': 'item1'}]  

然后我們對“下一級”應用相同的邏輯(制作一列'activities' )。

速度

對於測試,這是一種構建任意大小的df的方法,如示例:

n = 100_000
df = pd.DataFrame({
    'plan_id': np.random.randint(0, 20, size=n),
    'activity_id': np.random.randint(0, 20, size=n),
    'item_id': np.random.randint(0, 20, size=n),    
})
df = df.assign(**{
    k.replace('_id', '_name'): k.replace('_id', '_') + v
    for k, v in df.astype(str).items()
})

在這樣一個 100K df上,時間是:

%timeit to_grouped_dicts(df)
# 314 ms ± 940 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

在這種情況下,它實際上比單個簡單的.to_dict()快一點:

%timeit df.to_dict(orient='records')
# 509 ms ± 579 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

速度比取決於各個組的重復程度。 .to_dict()不做任何分組,所以它必須吐出每一行的每一個單元格。 如果發生的分組較少,則to_grouped_dicts()可能比.to_dict()慢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM