【问题标题】:Operation on MultiIndex Dataframe with condition带条件的 MultiIndex 数据帧的操作
【发布时间】:2021-12-22 20:05:06
【问题描述】:

我在 Python 中有一个 Pandas MultiIndex 数据框,它有两个级别的索引和如下所示的列:

miind = pd.MultiIndex.from_product([['A1','A2'],['B1','B2','B3']])
micol = pd.MultiIndex.from_product([['X1','X2'],['Y1','Y2','Y3']])
df = pd.DataFrame((np.arange(len(miind)*len(micol)) % 5).reshape(len(miind),len(micol)),
    index=miind, columns=micol)
print(df)
      X1       X2      
      Y1 Y2 Y3 Y1 Y2 Y3
A1 B1  0  1  2  3  4  0
   B2  1  2  3  4  0  1
   B3  2  3  4  0  1  2
A2 B1  3  4  0  1  2  3
   B2  4  0  1  2  3  4
   B3  0  1  2  3  4  0

我想,对于每一行,当 Y3 不为 0 时,将 Y1 和 Y2 除以 Y3。我不知道如何将条件 Y3>0 与元素选择结合起来。

最好的方法是什么? np.where(),一个掩码,还是只是索引?我访问 Y3 如下:

idx = pd.IndexSlice
print(df.loc[idx[:,:],idx[:,'Y3']] > 0)
          X1     X2
          Y3     Y3
A1 B1   True  False
   B2   True   True
   B3   True   True
A2 B1  False   True
   B2   True   True
   B3   True  False

编辑:

这就是我想要的,使用for 循环:

A = ['A1','A2']
B = ['B1','B2','B3']
X = ['X1','X2']
Y = ['Y1','Y2','Y3']
miind = pd.MultiIndex.from_product([A,B])
micol = pd.MultiIndex.from_product([X,Y])
df = pd.DataFrame((np.arange(len(miind)*len(micol)) % 5).reshape(len(miind),len(micol)), 
                  index=miind, columns=micol)
for i, a in enumerate(A):
    df1 =  df.loc[a]
    for j,b in enumerate(B):
        df2 = df1.loc[b]
        for k,x in enumerate(X):
            s1 = df2.loc[x]
            if s1['Y3'] > 0:
                df.loc[idx[a,b],idx[x,'Y1']] /= s1['Y3']
                df.loc[idx[a,b],idx[x,'Y2']] /= s1['Y3']
print(df)
             X1                     X2             
             Y1        Y2 Y3        Y1        Y2 Y3
A1 B1  0.000000  0.500000  2  3.000000  4.000000  0
   B2  0.333333  0.666667  3  4.000000  0.000000  1
   B3  0.500000  0.750000  4  0.000000  0.500000  2
A2 B1  3.000000  4.000000  0  0.333333  0.666667  3
   B2  4.000000  0.000000  1  0.500000  0.750000  4
   B3  0.000000  0.500000  2  3.000000  4.000000  0

但是,这个解决方案并不优雅,可能无法很好地扩展到更大的 DataFrames...

【问题讨论】:

    标签: python dataframe multi-index


    【解决方案1】:

    您可以堆叠和取消堆叠您的数据框:

    # stack the dataframe
    tmp = df.stack(level=0)
    
    # divide the columns of the stacked dataframe
    tmp.loc[tmp['Y3']!= 0, 'Y1'] /= tmp.loc[tmp['Y3']!= 0, 'Y3']
    tmp.loc[tmp['Y3']!= 0, 'Y2'] /= tmp.loc[tmp['Y3']!= 0, 'Y3']
    
    # unstack the divided dataframe
    tmp = tmp.unstack(level=2)
    

    此时,我们有:

                 Y1                  Y2           Y3   
                 X1        X2        X1        X2 X1 X2
    A1 B1  0.000000  3.000000  0.500000  4.000000  2  0
       B2  0.333333  4.000000  0.666667  0.000000  3  1
       B3  0.500000  0.000000  0.750000  0.500000  4  2
    A2 B1  3.000000  0.333333  4.000000  0.666667  0  3
       B2  4.000000  0.500000  0.000000  0.750000  1  4
       B3  0.000000  3.000000  0.500000  4.000000  2  0
    

    还不错,列的级别不是我们想要的。让我们继续……

    # reverse the column levels
    tmp.columns = pd.MultiIndex.from_tuples((j,i) for i,j in tmp.columns)
    
    # and sort the columns
    result = tmp.sort_index(axis=1)
    

    我们现在有如预期的那样:

                 X1                     X2             
                 Y1        Y2 Y3        Y1        Y2 Y3
    A1 B1  0.000000  0.500000  2  3.000000  4.000000  0
       B2  0.333333  0.666667  3  4.000000  0.000000  1
       B3  0.500000  0.750000  4  0.000000  0.500000  2
    A2 B1  3.000000  4.000000  0  0.333333  0.666667  3
       B2  4.000000  0.000000  1  0.500000  0.750000  4
       B3  0.000000  0.500000  2  3.000000  4.000000  0
    

    【讨论】:

      猜你喜欢
      • 2023-01-20
      • 2023-01-01
      • 1970-01-01
      • 2016-02-12
      • 2022-10-21
      • 2019-03-23
      • 1970-01-01
      • 2021-08-01
      • 2019-08-08
      相关资源
      最近更新 更多