【问题标题】:math operations between column in multiindex dataframe多索引数据框中列之间的数学运算
【发布时间】:2019-03-06 10:22:25
【问题描述】:

我有一个包含多索引列的数据框,我需要对其进行切片并在切片之间执行数学运算。

# sample df
idx=pd.IndexSlice
np.random.seed(123)
tuples = list(zip(*[['one', 'one', 'two', 'two', 'three', 'three'],['foo', 'bar', 'foo', 'bar', 'foo', 'bar']]))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(3, 6), index=['A', 'B', 'C'], columns=index)

如果我想在各个列之间执行加法/减法,我可以使用索引切片并这样做:

df.loc[:,idx['three','foo']] - df.loc[:,idx['two','foo']]

但是,如果我想使用更高级别的切片,它不起作用并返回 NaN:

# not working
df.loc[:,idx['three',:]] - df.loc[:,idx['two',:]]

有没有一种简单的方法来使用更高级别的 df 切片并仅添加/减去相应的列?我的数据框可能在多索引中包含数百列。谢谢

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    如果在输出中需要 MultiIndex,请使用 rename 用于同一级别的 od MultiIndex:

    df = df.loc[:,idx['three',:]] - df.loc[:,idx['two',:]].rename(columns={'two':'three'})
    print (df)
    first      three          
    second       foo       bar
    A      -0.861579  3.157731
    B      -1.944822  0.772031
    C       2.649912  2.621137
    

    优势是可以将两个级别重命名为新的索引名称并加入原始索引:

    df = (df.join(df.loc[:,idx['three',:]].rename(columns={'three':'four'}) - 
                  df.loc[:,idx['two',:]].rename(columns={'two':'four'})))
    print (df)
    first        one                 two               three                four  \
    second       foo       bar       foo       bar       foo       bar       foo   
    A      -1.085631  0.997345  0.282978 -1.506295 -0.578600  1.651437 -0.861579   
    B      -2.426679 -0.428913  1.265936 -0.866740 -0.678886 -0.094709 -1.944822   
    C       1.491390 -0.638902 -0.443982 -0.434351  2.205930  2.186786  2.649912   
    
    first             
    second       bar  
    A       3.157731  
    B       0.772031  
    C       2.621137  
    

    如果没有必要,使用DataFrame.xs:

    df1 = df.xs('three', axis=1, level=0) - df.xs('two', axis=1, level=0)
    print (df1)
    second       foo       bar
    A      -0.861579  3.157731
    B      -1.944822  0.772031
    C       2.649912  2.621137
    

    如果需要第一级,一个可能的解决方案是MultiIndex.from_product:

    df1 = df.xs('three', axis=1, level=0) - df.xs('two', axis=1, level=0)
    df1.columns = pd.MultiIndex.from_product([['new'], df1.columns], 
                                             names=['first','second'])
    print (df1)
    first        new          
    second       foo       bar
    A      -0.861579  3.157731
    B      -1.944822  0.772031
    C       2.649912  2.621137
    

    【讨论】:

    • 谢谢,重命名选项就像一个魅力。还有一件事-如果我也想重命名输出中的较低级别,那么完成它的最佳方法是什么?说四/ bar_delta, foo_delta ?
    • @whada - 使用df = df.rename(columns={'foo':'bar'}, level=1),但必须重命名所有值,因为同样的问题,得到 NaN。
    【解决方案2】:

    你可以试试DataFrame.xs(横截面):

    df.xs(('three'), axis=1) - df.xs(('two'), axis=1)
    

    【讨论】:

      【解决方案3】:

      在这种特殊情况下,最简单的方法可能是:

      df.loc[:, 'two'] - df.loc[:, 'three']
      

      您需要了解的有关 MultiIndex 的几乎所有信息都可以在 @coldspeed 的 canonicals 中找到

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-31
        • 1970-01-01
        • 2019-07-10
        • 2016-03-15
        相关资源
        最近更新 更多