2016-02-25 80 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