2015-06-19 141 views
2

假設我有以下數據框:索引數據幀後更新大熊貓多指標

arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], 
     ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']] 
tuples = list(zip(*arrays)) 
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second']) 
s = pd.DataFrame(np.random.randn(8, 2), index=index, columns=[0, 1]) 
s 

        0   1 
first second      
bar one -0.012581 1.421286 
     two -0.048482 -0.153656 
baz one -2.616540 -1.368694 
     two -1.989319 1.627848 
foo one -0.404563 -1.099314 
     two -2.006166 0.867398 
qux one -0.843150 -1.045291 
     two  2.129620 -2.697217 

我知道通過索引選擇子非數據幀:

temp = s.loc[('bar', slice(None)), slice(None)].copy() 
temp 

        0   1 
first second      
bar one -0.012581 1.421286 
     two -0.048482 -0.153656 

但是,如果我看的指數,原始索引的值仍然出現:

temp.index 
MultiIndex(levels=[[u'bar', u'baz', u'foo', u'qux'], [u'one', u'two']], 
     labels=[[0, 0], [0, 1]], 
     names=[u'first', u'second']) 

這對正常的數據幀不會發生。如果您編制索引,剩餘的副本(甚至視圖)只包含選定的索引/列。這是煩人,因爲我可能會經常做很多的大dataframes過濾,並在結束時,我想通過只是在做

df.index 
df 

這也發生了多指標列知道還剩下什麼指標。是否有更新索引/列並刪除空條目的正確方法?

要清楚,我希望過濾的數據幀具有相同的結構(多索引索引和列)。例如,我想做的事:

temp = s.loc[(('bar', 'foo'), slice(None)), :] 

但指數仍然有「巴茲」和「qux的價值觀:

MultiIndex(levels=[[u'bar', u'baz', u'foo', u'qux'], [u'one', u'two']], 
     labels=[[0, 0, 2, 2], [0, 1, 0, 1]], 
     names=[u'first', u'second']) 

要清楚,我想看看效果,我寫了這snippet消除多餘條目:

import pandas as pd 
def update_multiindex(df): 
    if isinstance(df.columns, pd.MultiIndex): 
     new_df = {key: df.loc[:, key] for key in df.columns if not df.loc[:,  key].empty}  
     new_df = pd.DataFrame(new_df) 
    else: 
     new_df = df.copy() 
    if isinstance(df.index, pd.MultiIndex): 
     new_df = {key: new_df.loc[key, :] for key in new_df.index if not  new_df.loc[key, :].empty} 
     new_df = pd.DataFrame(new_df).T 
    return new_df 

temp = update_multiindex(temp).index 
temp 
MultiIndex(levels=[[u'bar', u'foo'], [u'one', u'two']], 
     labels=[[0, 0, 1, 1], [0, 1, 0, 1]]) 
+0

我有這個確切的問題,我想你會發現Ezekiel Kruglick(在這個頁面上)的答案可以最好地解決你的問題。我添加了一個.unique()來刪除重複項:'df.index.get_level_values(some_level).unique()' –

回答

0

嘗試使用droplevel

temp.index = temp.index.droplevel() 

>>> temp 
       0   1 
second      
one  0.450819 -1.071271 
two -0.371563 0.411808 

>>> temp.index 
Index([u'one', u'two'], dtype='object') 

當列打交道,這是同樣的事情:

df.columns = df.columns.droplevel() 

您還可以使用xsdrop_level參數設置爲True(默認值爲False):

>>> s.xs('bar', drop_level=True) 
       0   1 
second      
one  0.450819 -1.071271 
two -0.371563 0.411808 
+1

這是一個未公開的方法,截至0.16.2。任何想法爲什麼熊貓沒有'MultiIndex()'的API文檔? – Andreus

+0

不知道爲什麼沒有記錄水滴。這裏是MultiIndex的文檔:http://pandas.pydata.org/pandas-docs/stable/advanced.html – Alexander

+0

我不想放棄關卡。我的例子是基本的,但我想過濾一個級別的多個值,並消除其他人。因此,我希望具有相同的結構,但只在過濾的數據幀索引和/或列中具有正確的值。 – user1350191

0

s索引與temp索引之間存在差異:

In [25]: s.index 
Out[25]: 
MultiIndex(levels=[[u'bar', u'baz', u'foo', u'qux'], [u'one', u'two']], 
      labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]], 
      names=[u'first', u'second']) 

In [26]: temp.index 
Out[26]: 
MultiIndex(levels=[[u'bar', u'baz', u'foo', u'qux'], [u'one', u'two']], 
      labels=[[0, 0], [0, 1]], 
      names=[u'first', u'second']) 

注意MultiIndex中的labels是不同的。

+0

有趣的是,我想我得到爲什麼這些級別仍然在那裏,但如果它們被有效地消除了(即沒有標籤指向這些值),那麼爲什麼要保留它們? – user1350191

+0

我的猜測是,離開MultiIndex的水平是有效的。如果您更改了關卡,則每次切片時都需要更新MultiIndex的標籤。 – MangoHands

2

兩點。首先,我認爲你可能想要做一些對你不利的事情。我知道這很煩人,你在你的過濾索引中有很多額外的東西,但是如果你重建索引以排除缺失的分類值,那麼你的新索引將與其他索引和原始索引不兼容。

這就是說,我懷疑(但不知道)MultiIndex使用這種方式是建立在CategoricalIndex之上,它有方法remove_unused_levels()。它可能包裹MultiIndex,但我不能說,因爲...

其次,MultiIndex明顯缺少pandas API documentation。我不使用MultiIndex,但如果您經常使用它,您可能會考慮在GitHub上尋找和/或打開關於此的票。除此之外,如果您想查找有關MultiIndex可用功能的確切信息,則可能需要通過source code

+0

好點。謝謝! – user1350191

1

如果我理解正確,你的使用模式,你可能會得到兩全其美。我重點關注:

這是煩人,因爲我可能會經常做很多篩選的就大 dataframes,並在結束時,我想知道的是什麼 通過只是在做

DF左指數.index df

這也適用於多索引列。是否有更新索引/列並刪除空條目的正確方法 ?

考慮(1)是你想知道什麼是剩下的索引。考慮(2)就像上面提到的那樣,如果你修改多重索引,你不能將任何數據重新合併到你的原始數據中,而且它的一些非顯而易見的步驟也不會被鼓勵。

底層的基本原理是,如果任何行或列已被刪除,且索引不會爲多索引返回更新的內容,並且這不被視爲錯誤,因爲這不是MultiIndexes的批准使用(請閱讀:github.com/pydata/pandas/issues/3686)。 MultiIndex當前內容的有效API訪問權限爲get_level_values。

那麼它會適合你的需要來調整你的實踐使用它?

df.index.get_level_values(-put your level name or number here-) 

對於多指數這是批准的API訪問技術,並有一些很好的理由。如果您使用get_level_values而不是.index,那麼您將能夠獲取當前內容,同時保留所有信息以防您想要重新合併修改後的數據,或者與原始索引進行匹配以進行比較,分組等。 。

這是否符合您的需求?