मेरे पास डेटाफ्रेम है जो नीचे जैसा दिखता है। इसमें योजनाओं, गतिविधियों और वस्तुओं के बारे में जानकारी शामिल है। प्रत्येक योजना में कई गतिविधियाँ शामिल हैं, और प्रत्येक गतिविधि में कई आइटम शामिल हैं।

| 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')

मुझे यकीन नहीं है कि यह सबसे तेज़ समाधान है। कोई अन्य विचार?

1
psowa001 30 जिंदा 2021, 16:05
2
उपयोगी हो सकता है DataFrame.to_jsonदेखें
 – 
Ch3steR
30 जिंदा 2021, 16:37
लेकिन यह वही नहीं है जो ओपी चाहता है: वे कुछ चाबियों द्वारा समूहबद्ध करने के बाद पदानुक्रमित रूप से संरचना करना चाहते हैं। न तो .to_json() और न ही .to_dict() इसे आसानी से हासिल कर पाएंगे। कुछ समूह बनाने की जरूरत है। साथ ही, .to_json() केवल .to_dict() आउटपुट की एक स्ट्रिंग उत्पन्न करता है। ओपी एक dict चाहता है, str नहीं।
 – 
Pierre D
30 जिंदा 2021, 17:53

1 उत्तर

सबसे बढ़िया उत्तर

इस बारे में कैसा है:

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'}]}]}]

व्याख्या

विचार किसी दिए गए समूह के लिए dicts की सूची एकत्र करना है। उदाहरण के लिए, पहली पंक्ति:

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() से धीमा हो सकता है।

1
Pierre D 30 जिंदा 2021, 19:44