नेस्टेड शब्दकोश में वस्तुओं से पंडों डेटाफ्रेम का निर्माण


90

मान लीजिए कि मेरे पास संरचना के साथ एक नेस्टेड डिक्शनरी 'user_dict' है:

  • लेवल 1: UserId (लॉन्ग इंटेगर)
  • स्तर 2: श्रेणी (स्ट्रिंग)
  • स्तर 3: मिश्रित विशेषताएँ (फ़्लोट्स, इनट्स, आदि ..)

उदाहरण के लिए, इस शब्दकोश की एक प्रविष्टि होगी:

user_dict[12] = {
    "Category 1": {"att_1": 1, 
                   "att_2": "whatever"},
    "Category 2": {"att_1": 23, 
                   "att_2": "another"}}

प्रत्येक आइटम में user_dictसमान संरचना होती है और user_dictइसमें बड़ी संख्या में आइटम होते हैं, जिन्हें मैं एक पांडा डेटाफ़्रेम को खिलाना चाहता हूं, जो विशेषताओं से श्रृंखला का निर्माण करते हैं। इस मामले में एक पदानुक्रमित सूचकांक उपयोगी होगा।

विशेष रूप से, मेरा सवाल यह है कि क्या डेटाफ़्रेम निर्माता को यह समझने में मदद करने का कोई तरीका मौजूद है कि श्रृंखला को शब्दकोश में "स्तर 3" के मूल्यों से बनाया जाना चाहिए?

अगर मैं कुछ इस तरह की कोशिश करता हूं:

df = pandas.DataFrame(users_summary)

"स्तर 1" (उपयोगकर्ता आईडी) के आइटम को कॉलम के रूप में लिया जाता है, जो कि मैं जो हासिल करना चाहता हूं उसके विपरीत है (उपयोगकर्ता आईडी के सूचकांक के रूप में)।

मुझे पता है कि मैं डिक्शनरी प्रविष्टियों पर ध्यान देने के बाद श्रृंखला का निर्माण कर सकता हूं, लेकिन अगर अधिक सीधा रास्ता है तो यह बहुत उपयोगी होगा। एक समान प्रश्न पूछ रहा होगा कि क्या किसी फ़ाइल में सूचीबद्ध json ऑब्जेक्ट्स से पांडा डेटाफ़्रेम का निर्माण संभव है।


सरल विकल्पों के लिए यह उत्तर देखें ।
सीएस 95 पी

जवाबों:


141

एक पांडा मल्टीआंडेक्स में ट्यूपल्स की एक सूची होती है। तो सबसे प्राकृतिक दृष्टिकोण आपके इनपुट को तानाशाही के आकार में बदलना होगा ताकि इसकी कुंजी आपके द्वारा आवश्यक बहु-सूचकांक मूल्यों के अनुरूप हो। तब आप केवल pd.DataFrame.from_dictविकल्प का उपयोग करके अपने डेटाफ़्रेम का निर्माण कर सकते हैं orient='index':

user_dict = {12: {'Category 1': {'att_1': 1, 'att_2': 'whatever'},
                  'Category 2': {'att_1': 23, 'att_2': 'another'}},
             15: {'Category 1': {'att_1': 10, 'att_2': 'foo'},
                  'Category 2': {'att_1': 30, 'att_2': 'bar'}}}

pd.DataFrame.from_dict({(i,j): user_dict[i][j] 
                           for i in user_dict.keys() 
                           for j in user_dict[i].keys()},
                       orient='index')


               att_1     att_2
12 Category 1      1  whatever
   Category 2     23   another
15 Category 1     10       foo
   Category 2     30       bar

एक वैकल्पिक दृष्टिकोण घटक डेटाफ्रेम को समाप्‍त करके आपके डेटाफ्रेम का निर्माण करना होगा:

user_ids = []
frames = []

for user_id, d in user_dict.iteritems():
    user_ids.append(user_id)
    frames.append(pd.DataFrame.from_dict(d, orient='index'))

pd.concat(frames, keys=user_ids)

               att_1     att_2
12 Category 1      1  whatever
   Category 2     23   another
15 Category 1     10       foo
   Category 2     30       bar

11
क्या मनमाना गहराई से रगड़ सूचियों के साथ काम करने के लिए इसे सामान्य करने का एक उचित तरीका है? उदाहरण के लिए एक मनमानी गहराई को सूचीबद्ध करता है, जहां कुछ शाखाएं दूसरों की तुलना में कम हो सकती हैं, और छोटी शाखाओं के अंत तक नहीं पहुंचने पर कोई भी या नैनो का उपयोग नहीं किया जाता है?
n

5
क्या आपने पंडों के जोंस समर्थन (io टूल्स) और सामान्यीकरण को देखा है? pandas.pydata.org/pandas-docs/dev/io.html#normalization
Wouter Overmeire

1
मेरे लिए, पहली विधि ने एक सूचकांक के साथ एक डेटाफ्रेम बनाया, जिसमें ट्यूपल्स थे। दूसरा तरीका वांछित / उम्मीद के अनुसार काम किया!
Arturomp

इन नए कॉलमों का नाम कैसे दिया जाए, इस पर कोई सुझाव? उदाहरण के लिए, यदि मैं चाहता हूं कि ये संख्याएँ 12 और 15 कॉलम 'id' में हों।
चर्ममुश्किन

1
@cheremushkin 12 और 15 अब 'id' पंक्ति में हैं, यदि आप ट्रैन्ड करते हैं ( pandas.pydata.org/pandas-docs/stable/reference/api/… ) तो वे कॉलम 'id' में हैं। आप अनस्टैक ( pandas.pydata.org/pandas-docs/stable/reference/api/… ) भी कर सकते हैं। यह सब इस बात पर निर्भर करता है कि आपको वास्तव में क्या चाहिए।
राउटर ओवरमीयर

33

pd.concatएक शब्दकोश स्वीकार करता है। इसे ध्यान में रखते हुए, उप-फ़्रेमों के लिए एक शब्दकोश मानचित्रण कुंजी बनाने के लिए एक शब्दकोश समझ का उपयोग करके सादगी और प्रदर्शन के मामले में वर्तमान में स्वीकृत जवाब पर सुधार करना संभव है ।

pd.concat({k: pd.DataFrame(v).T for k, v in user_dict.items()}, axis=0)

या,

pd.concat({
        k: pd.DataFrame.from_dict(v, 'index') for k, v in user_dict.items()
    }, 
    axis=0)

              att_1     att_2
12 Category 1     1  whatever
   Category 2    23   another
15 Category 1    10       foo
   Category 2    30       bar

4
प्रतिभाशाली! बहुत बेहतर :)
pg2455

3
यदि आप अभी भी एक और आंतरिक श्रेणी रखते हैं तो आप इसे कैसे करेंगे? इस तरह के रूप में 12:{cat1:{cat11:{att1:val1,att2:val2}}}। दूसरे शब्दों में: कोई एक अप्रासंगिक श्रेणी के समाधान का सामान्यीकरण कैसे करेगा?
लुकास Aimaretto

1
@LucasAimaretto आमतौर पर मनमाने ढंग से नेस्टेड संरचनाओं के साथ चपटा किया जा सकता है json_normalize। मेरे पास एक और उत्तर है जो दिखाता है कि यह कैसे काम करता है।
cs95

1
काम नहीं करता है अगर vउदाहरण के लिए एक पूर्णांक है। क्या आप ऐसे मामले में एक विकल्प जानते हैं?
sk

11

इसलिए मैंने डिक्शनरी के माध्यम से पुनरावृति के लिए लूप के लिए उपयोग किया, लेकिन एक चीज जो मैंने पाया है कि बहुत तेजी से काम करता है एक पैनल और फिर एक डेटाफ़्रेम में परिवर्तित होता है। कहते हैं कि आपके पास एक डिक्शनरी है

import pandas as pd
d
{'RAY Index': {datetime.date(2014, 11, 3): {'PX_LAST': 1199.46,
'PX_OPEN': 1200.14},
datetime.date(2014, 11, 4): {'PX_LAST': 1195.323, 'PX_OPEN': 1197.69},
datetime.date(2014, 11, 5): {'PX_LAST': 1200.936, 'PX_OPEN': 1195.32},
datetime.date(2014, 11, 6): {'PX_LAST': 1206.061, 'PX_OPEN': 1200.62}},
'SPX Index': {datetime.date(2014, 11, 3): {'PX_LAST': 2017.81,
'PX_OPEN': 2018.21},
datetime.date(2014, 11, 4): {'PX_LAST': 2012.1, 'PX_OPEN': 2015.81},
datetime.date(2014, 11, 5): {'PX_LAST': 2023.57, 'PX_OPEN': 2015.29},
datetime.date(2014, 11, 6): {'PX_LAST': 2031.21, 'PX_OPEN': 2023.33}}}

आदेश

pd.Panel(d)
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 2 (major_axis) x 4 (minor_axis)
Items axis: RAY Index to SPX Index
Major_axis axis: PX_LAST to PX_OPEN
Minor_axis axis: 2014-11-03 to 2014-11-06

जहाँ pd.Panel (d) [आइटम] एक डेटाफ्रेम देता है

pd.Panel(d)['SPX Index']
2014-11-03  2014-11-04  2014-11-05 2014-11-06
PX_LAST 2017.81 2012.10 2023.57 2031.21
PX_OPEN 2018.21 2015.81 2015.29 2023.33

फिर आप इसे डेटाफ्रेम में बदलने के लिए कमांड to_frame () को हिट कर सकते हैं। मैं रीसेट_इंडेक्स का उपयोग करने के साथ-साथ प्रमुख और मामूली अक्ष को स्तंभों में बदलने के लिए उन्हें सूचक के रूप में उपयोग करता हूं।

pd.Panel(d).to_frame().reset_index()
major   minor      RAY Index    SPX Index
PX_LAST 2014-11-03  1199.460    2017.81
PX_LAST 2014-11-04  1195.323    2012.10
PX_LAST 2014-11-05  1200.936    2023.57
PX_LAST 2014-11-06  1206.061    2031.21
PX_OPEN 2014-11-03  1200.140    2018.21
PX_OPEN 2014-11-04  1197.690    2015.81
PX_OPEN 2014-11-05  1195.320    2015.29
PX_OPEN 2014-11-06  1200.620    2023.33

अंत में, यदि आप जिस तरह से फ्रेम को देखते हैं, वह आपको to_frame () को देखने से पहले उपस्थिति को बदलने के लिए पैनल के ट्रांसफ़ेक्ट फ़ंक्शन का उपयोग कर सकता है, तो यहां http://pandas.pydata.org/pandas-docs/dev/generated देखें /pandas.Panel.transpose.html

उदाहरण के तौर पर

pd.Panel(d).transpose(2,0,1).to_frame().reset_index()
major        minor  2014-11-03  2014-11-04  2014-11-05  2014-11-06
RAY Index   PX_LAST 1199.46    1195.323     1200.936    1206.061
RAY Index   PX_OPEN 1200.14    1197.690     1195.320    1200.620
SPX Index   PX_LAST 2017.81    2012.100     2023.570    2031.210
SPX Index   PX_OPEN 2018.21    2015.810     2015.290    2023.330

उम्मीद है की यह मदद करेगा।


8
पैनल को पंडों के हाल के संस्करणों में लिखा गया है (लेखन के समय v0.23)।
सीएस 95 पी

6

यदि कोई व्यक्ति "लॉन्ग फॉर्मेट" में डेटा फ्रेम प्राप्त करना चाहता है (पत्ती का मूल्य एक ही प्रकार है) बिना मल्टीएंडेक्स के, आप यह कर सकते हैं:

pd.DataFrame.from_records(
    [
        (level1, level2, level3, leaf)
        for level1, level2_dict in user_dict.items()
        for level2, level3_dict in level2_dict.items()
        for level3, leaf in level3_dict.items()
    ],
    columns=['UserId', 'Category', 'Attribute', 'value']
)

    UserId    Category Attribute     value
0       12  Category 1     att_1         1
1       12  Category 1     att_2  whatever
2       12  Category 2     att_1        23
3       12  Category 2     att_2   another
4       15  Category 1     att_1        10
5       15  Category 1     att_2       foo
6       15  Category 2     att_1        30
7       15  Category 2     att_2       bar

(मुझे पता है कि मूल प्रश्न शायद (मैं) के स्तर 1 और 2 को मल्टीइंडेक्स और स्तर 3 को कॉलम के रूप में और (II) को मानने के अन्य तरीकों के बारे में पूछता है। और उपयोगी (I.): मेरे जैसे लोगों के लिए जिन्होंने इस आकार में नेस्टेड डिक्टेट पाने का तरीका खोजने की कोशिश की है और Google केवल इस प्रश्न को वापस करता है और (II): क्योंकि अन्य उत्तरों में कुछ पुनरावृत्ति भी शामिल हैं और मुझे यह पता चलता है। दृष्टिकोण लचीला और पढ़ने में आसान; प्रदर्शन के बारे में निश्चित नहीं है, हालांकि।)


0

सत्यापित उत्तर पर निर्माण, मेरे लिए इसने सबसे अच्छा काम किया:

ab = pd.concat({k: pd.DataFrame(v).T for k, v in data.items()}, axis=0)
ab.T
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.