2012-11-26 144 views
35

假設我有一個嵌套詞典 'user_dict' 與結構:構建大熊貓數據幀在嵌套字典

級別1:用戶ID(長整型)

級別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」包含了大量的,我想喂到大熊貓數據幀的項目,構建從系列屬性。在這種情況下,分層索引對於此目的會很有用。

具體來說,我的問題是,是否存在一種方法來幫助DataFrame構造函數理解該系列應該從字典中的「級別3」的值構建?

如果我嘗試類似:

df = pandas.DataFrame(users_summary) 

的項目在「1級」(用戶ID的)被視爲列,這是我所想達到(有用戶ID爲索引相反)。

我知道我可以在遍歷字典條目後構建系列,但是如果有更直接的方法,這將非常有用。一個類似的問題是詢問是否可以從文件中列出的json對象構造一個pandas DataFrame。

回答

51

熊貓MultiIndex由元組列表組成。所以最自然的方法是重塑你的輸入字典,使它的鍵是你需要的多索引值對應的元組。然後,你可以建造使用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 

另一種方法是通過連接組件dataframes建立自己的數據框起來:

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 
+1

有沒有一種合理的方式來推廣這個工作與任意深度不整齊的列表?例如列表到任意深度,其中一些分支可能比其他分支短,當較短的分支未達到結尾時使用None或nan? – naught101

+3

你看過熊貓JSON支持(io工具)和規範化嗎? http://pandas.pydata.org/pandas-docs/dev/io.html#normalization –

+0

拯救我的生命!!!!!!!!!!學習很多!謝謝 – Wen

10

所以我用一個用於循環遍歷字典的for循環,但是我發現有一件事情更快地轉化爲面板,然後轉換爲數據框。 假設你有一個字典d

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 ()把它變成一個數據框。我還使用reset_index以將主軸和副軸轉換爲列,而不是將它們作爲索引。

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 

希望這會有所幫助。

+0

如此優雅的解決方案! – vk1011

+0

這很容易理解。謝謝。 – Moondra