2016-07-06 11 views
21

मेरे पास एक postgreSQL डेटाबेस में डेटा सहेजा गया है। मैं Python2.7 का उपयोग करके इस डेटा को पूछ रहा हूं और इसे पांडस डेटाफ्रेम में बदल रहा हूं। हालांकि, इस डेटाफ्रेम के अंतिम कॉलम में इसके मूल्यों का एक शब्दकोश (या सूची?) है। DataFrame इस तरह दिखता है:अलग-अलग कॉलम में पांडस कॉलम के अंदर शब्दकोश/सूची को विभाजित करना

[1] df 
Station ID  Pollutants 
8809   {"a": "46", "b": "3", "c": "12"} 
8810   {"a": "36", "b": "5", "c": "8"} 
8811   {"b": "2", "c": "7"} 
8812   {"c": "11"} 
8813   {"a": "82", "c": "15"} 

मैं अलग-अलग कॉलम में इस स्तंभ को विभाजित करने की जरूरत है ताकि DataFrame इस तरह दिखता है:

[2] df2 
Station ID  a  b  c 
8809   46  3  12 
8810   36  5  8 
8811   NaN 2  7 
8812   NaN NaN  11 
8813   82  NaN  15 

प्रमुख मुद्दा रहा हो रही है कि सूचियों नहीं हैं वही लंबाई लेकिन सभी सूचियों में केवल एक ही 3 मान होते हैं: ए, बी, और सी। और वे हमेशा एक ही क्रम में दिखाई देते हैं (पहला, बी दूसरा, सी तीसरा)।

निम्नलिखित कोड काम करने के लिए उपयोग किया गया और ठीक वही वापस लौटा जो मैं चाहता था (डीएफ 2)।

[3] df 
[4] objs = [df, pandas.DataFrame(df['Pollutant Levels'].tolist()).iloc[:, :3]] 
[5] df2 = pandas.concat(objs, axis=1).drop('Pollutant Levels', axis=1) 
[6] print(df2) 

मैं पिछले सप्ताह इस कोड को चला रहा था और यह ठीक काम कर रहा था। लेकिन अब मेरी कोड टूट गया है और लाइन [4] से इस त्रुटि मिलती है:

IndexError: out-of-bounds on slice (end) 

मैं कोड के लिए कोई परिवर्तन नहीं किए, लेकिन अब त्रुटि हो रही है। मुझे लगता है कि यह मेरी विधि के कारण मजबूत या उचित नहीं है।

सूचियों के इस कॉलम को अलग-अलग कॉलम में विभाजित करने के बारे में कोई सुझाव या मार्गदर्शन अत्यधिक सराहना की जाएगी!

संपादित करें: मुझे लगता है .tolist() और .apply तरीकों मेरी कोड पर काम नहीं कर रहे हैं, क्योंकि यह एक यूनिकोड स्ट्रिंग, यानी है:

#My data format 
u{'a': '1', 'b': '2', 'c': '3'} 

#and not 
{u'a': '1', u'b': '2', u'c': '3'} 

डेटा इस प्रारूप में PostgreSQL डेटाबेस से आयात कर रहा है । इस मुद्दे के साथ कोई मदद या विचार? यूनिकोड को बदलने का कोई तरीका है?

+0

मैं एक अलग समाधान के साथ उत्तर दिया, लेकिन अपने कोड वास्तव में भी ठीक काम करना चाहिए। नीचे मेरे डमी उदाहरण का उपयोग करके, यह पांडा 0.18.1 का उपयोग करके काम करता है अगर मैं 'iloc' भाग – joris

+0

छोड़ देता हूं इसका हिस्सा यह है कि 'iloc [:,: 3]' मानता है कि वहां 3 आइटम होंगे, और शायद हालिया डेटा स्लाइस में केवल 1 या 2 होता है (उदाहरण के लिए 'इंडेक्स 8813'' में कोई 'बी' नहीं होता है)? – dwanderson

उत्तर

35

स्ट्रिंग को एक वास्तविक dict में बदलने के लिए, आप df['Pollutant Levels'].map(eval) कर सकते हैं। इसके बाद, नीचे दिए गए समाधान का उपयोग विभिन्न स्तंभों में कन्वर्ट करने के लिए किया जा सकता है।


एक छोटा सा उदाहरण का उपयोग करना, आप .apply(pd.Series) उपयोग कर सकते हैं:

In [2]: df = pd.DataFrame({'a':[1,2,3], 'b':[{'c':1}, {'d':3}, {'c':5, 'd':6}]}) 

In [3]: df 
Out[3]: 
    a     b 
0 1   {u'c': 1} 
1 2   {u'd': 3} 
2 3 {u'c': 5, u'd': 6} 

In [4]: df['b'].apply(pd.Series) 
Out[4]: 
    c d 
0 1.0 NaN 
1 NaN 3.0 
2 5.0 6.0 

dataframe के बाकी के साथ संयोजित करने के लिए, आप ऊपर परिणाम के साथ अन्य स्तंभों concat कर सकते हैं:

In [7]: pd.concat([df.drop(['b'], axis=1), df['b'].apply(pd.Series)], axis=1) 
Out[7]: 
    a c d 
0 1 1.0 NaN 
1 2 NaN 3.0 
2 3 5.0 6.0 

अपने कोड का उपयोग करके, यह भी काम करता है अगर मैंछोड़ देता हूंहिस्सा:

In [15]: pd.concat([df.drop('b', axis=1), pd.DataFrame(df['b'].tolist())], axis=1) 
Out[15]: 
    a c d 
0 1 1.0 NaN 
1 2 NaN 3.0 
2 3 5.0 6.0 
+2

मैं लंबे समय से 'pd.DataFrame (df [col] .tolist()) का उपयोग कर रहा हूं, कभी भी 'लागू (pd.Series)' के बारे में सोचा नहीं। बहुत अच्छा। – ayhan

+0

अब मुझे समस्या का एहसास है। .apply (pd.Series) मेरे डेटासेट पर काम नहीं कर रहा है क्योंकि पूरी पंक्ति एक यूनिकोड स्ट्रिंग है। यह है: u '{' a ':' 1 ',' b ':' 2 ',' c ':' 3 '} और नहीं {u'a': '1', u'b ':' 2 ', u'c ':' 3 '} जैसे आपके समाधान दिखाते हैं। तो कोड इसे 3 पहचानने योग्य कॉलम में विभाजित नहीं कर सकता है। – llaffin

+0

@ayhan वास्तव में, इसका परीक्षण किया, और 'डेटाफ्रेम (डीएफ [' कोल ']। सूची())' दृष्टिकोण दृष्टिकोण के मुकाबले काफी तेज है! – joris

4

इस प्रयास करें: डेटा एसक्यूएल से लौटे एक Dict में परिवर्तित करने के लिए किया है। या यह "Pollutant Levels" हो सकता है एक पंक्ति में अब Pollutants'

StationID     Pollutants 
0  8809 {"a":"46","b":"3","c":"12"} 
1  8810 {"a":"36","b":"5","c":"8"} 
2  8811   {"b":"2","c":"7"} 
3  8812     {"c":"11"} 
4  8813   {"a":"82","c":"15"} 


df2["Pollutants"] = df2["Pollutants"].apply(lambda x : dict(eval(x))) 
df3 = df2["Pollutants"].apply(pd.Series) 

    a b c 
0 46 3 12 
1 36 5 8 
2 NaN 2 7 
3 NaN NaN 11 
4 82 NaN 15 


result = pd.concat([df, df3], axis=1).drop('Pollutants', axis=1) 
result 

    StationID a b c 
0  8809 46 3 12 
1  8810 36 5 8 
2  8811 NaN 2 7 
3  8812 NaN NaN 11 
4  8813 82 NaN 15 
0

है:

df = pd.concat([df['a'], df.b.apply(pd.Series)], axis=1)` 
संबंधित मुद्दे