无法使用pandas groupby.apply

时间:2018-11-09 04:55:09

标签: python pandas dataframe pandas-groupby

最初我有下表:

df=pd.DataFrame(
    np.arange(4*8).reshape(4,8),
    index=list('abcd'),
    columns=pd.MultiIndex.from_arrays([list('EEEETTTT'), list('XXYYZZWW'), list('rsrsrsrs')] )
)

    E               T            
    X       Y       Z       W    
    r   s   r   s   r   s   r   s
a   0   1   2   3   4   5   6   7
b   8   9  10  11  12  13  14  15
c  16  17  18  19  20  21  22  23
d  24  25  26  27  28  29  30  31

我在'V'多索引列旁边添加一个名为( , ,'s')的新列,如下所示:

    E                     T                  
    X          Y          W          Z       
    r   s  V   r   s  V   r   s  V   r   s  V
a   0   1  0   2   3  0   6   7  0   4   5  0
b   8   9  0  10  11  0  14  15  0  12  13  0
c  16  17  0  18  19  0  22  23  0  20  21  0
d  24  25  0  26  27  0  30  31  0  28  29  0

我运行以下代码来获得以上结果:

dfl=[]
for name, x in df.groupby(level=[0, 1], axis=1):
    index = pd.IndexSlice
    x.loc[:,index[name[0],name[1],'V']]= 0
    dfl.append(x)

pd.concat(dfl, axis=1) 

现在,我尝试了以下“替代”方式来获得相同的结果:

def f(x):
    idx = pd.IndexSlice
    x.loc[:, idx[x.name[0], x.name[1], 'V']]=0
    return x

df.groupby(level=[0,1], axis=1).apply(f)

但是,令我惊讶的是,结果表保持不变:

    E               T            
    X       Y       Z       W    
    r   s   r   s   r   s   r   s
a   0   1   2   3   4   5   6   7
b   8   9  10  11  12  13  14  15
c  16  17  18  19  20  21  22  23
d  24  25  26  27  28  29  30  31

pandas groupby.appy(func)应该允许func返回任何大小甚至标量的数据框。

这可能是个错误吗?

1 个答案:

答案 0 :(得分:2)

partial bugMutiIndex in columns的分组有关。

如果使用MultiIndex in index,则只需进行少量修改即可-删除用于分组的级别以避免重复级别。

通过对MultiIndex in index进行转置来修改您的解决方案,应用函数并向后转置:

def f(x):
    idx = pd.IndexSlice
    x.loc[idx[x.name[0], x.name[1], 'V'], :]=0
    x.index = x.index.droplevel([0,1])
    return x

df = df.T.groupby(level=[0,1], axis=0).apply(f).T.astype(int)
print (df)
    E                     T                  
    X          Y          W          Z       
    r   s  V   r   s  V   r   s  V   r   s  V
a   0   1  0   2   3  0   6   7  0   4   5  0
b   8   9  0  10  11  0  14  15  0  12  13  0
c  16  17  0  18  19  0  22  23  0  20  21  0
d  24  25  0  26  27  0  30  31  0  28  29  0

def f(x):
    idx = pd.IndexSlice
    x.loc[idx[x.name[0], x.name[1], 'V'], :]=0
    return x

df = df.T.groupby(level=[0,1], axis=0).apply(f).T.astype(int)
print (df)
    E                     T                  
    X          Y          W          Z       
    E          E          T          T       
    X          Y          W          Z       
    r   s  V   r   s  V   r   s  V   r   s  V
a   0   1  0   2   3  0   6   7  0   4   5  0
b   8   9  0  10  11  0  14  15  0  12  13  0
c  16  17  0  18  19  0  22  23  0  20  21  0
d  24  25  0  26  27  0  30  31  0  28  29  0