2016-02-25 77 views
3

我有以下形式的多級數據幀:應用類似的功能,以多級大熊貓數據幀

df = pd.DataFrame([[1,'A',2,'B',1,'B'],[2,'B',2,'B',2,'A'],[1,'A',1,'A',1,'A'],[1,'B',2,'A',2,'B']], 
        columns=pd.MultiIndex.from_tuples([('S1','Num'),('S1','Let'),('S2','Num'),('S2','Let'),('S3','Num'),('S3','Let')])) 

    S1  S2  S3  
    Num Let Num Let Num Let 
0 1 A 2 B 1 B 
1 2 B 2 B 2 A 
2 1 A 1 A 1 A 
3 1 B 2 A 2 B 

如何創建一個新的數據幀,使得每級零列的選擇,如果讓=='B '那麼它設置Num = 3?基本上我想獲得以下數據框:

S1  S2  S3  
    Num Let Num Let Num Let 
0 1 A 3 B 3 B 
1 3 B 3 B 2 A 
2 1 A 1 A 1 A 
3 3 B 2 A 3 B 

回答

4

一種方法是在位置上工作,使用ilocwhere

>>> df.iloc[:,0::2] = df.iloc[:,0::2].where((df.iloc[:,1::2]!="B").values, 3) 
>>> df 
    S1  S2  S3  
    Num Let Num Let Num Let 
0 1 A 3 B 3 B 
1 3 B 3 B 2 A 
2 1 A 1 A 1 A 
3 3 B 2 A 3 B 

它使用數組

>>> (df.iloc[:,1::2]!="B").values 
array([[ True, False, False], 
     [False, False, True], 
     [ True, True, True], 
     [False, True, False]], dtype=bool) 

決定我們只需要保留原始值。我們必須堅持.values在那裏,否則熊貓試圖對齊框架,我們正在手動做。

如果你堅持不使用iloc,那麼事情會變得有點棘手。一種方法是使用xsupdate

>>> df.update(df.xs("Num", level=1, axis=1, drop_level=False).where(
       df.xs("Let", level=1, axis=1, drop_level=False).values != "B", 3)) 
>>> df 
    S1  S2  S3  
    Num Let Num Let Num Let 
0 1 A 3 B 3 B 
1 3 B 3 B 2 A 
2 1 A 1 A 1 A 
3 3 B 2 A 3 B 

或者,如果您的柱lexsorted,你可以使用locslice(None)

>>> df = df.sort_index(axis=1) 
>>> nummask = slice(None), "Num" 
>>> letmask = slice(None), "Let" 
>>> df.loc[:, nummask] = df.loc[:, nummask].where((df.loc[:, letmask] != "B").values, 3) 
>>> df 
    S1  S2  S3  
    Let Num Let Num Let Num 
0 A 1 B 3 B 3 
1 B 3 B 3 A 2 
2 A 1 A 1 A 1 
3 B 3 A 2 B 3 

這可以簡化,有些使用IndexSlice:

>>> df = df.sort_index(axis=1) 
>>> idx = pd.IndexSlice 
>>> df.loc[:,idx[:,"Num"]] = df.loc[:,idx[:,"Num"]].where((df.loc[:,idx[:,"Let"]] != "B").values, 3) 
>>> df 
    S1  S2  S3  
    Let Num Let Num Let Num 
0 A 1 B 3 B 3 
1 B 3 B 3 A 2 
2 A 1 A 1 A 1 
3 B 3 A 2 B 3 
+0

謝謝!這工作。但有沒有辦法做到這一點,而不使用iloc?我的意思是通過使用列名而不是他們的數字? – JavNoor

+0

完美!謝謝。這就是我一直在尋找的東西。 – JavNoor