多索引数据帧的每一行的相减表(差)

时间:2018-07-30 00:14:46

标签: python pandas

我正在尝试从同一数据帧中的每隔一行中减去每一行。我见过this。但是那里的代码不适用于多索引。

这是我拥有的数据框的结构

                 a  c  z
index name          
0       foo      15  8  0
        bar      4   1  0
        baz      7   2  0
        toto     12  3  0
        titi     5   0  0
1       foo      8   6  0
        bar      4   1  0
        baz      6   3  0
        toto     5   1  0
        titi     6  0  0

我想要的结构如下:

index name1 name2  a    c  z
0      foo   bar   11   7  0
       foo   baz   8    6  0
       bar   baz   -3  -1  0

我已经尝试了2件事。第一个不保留name1name2,并且在链接中基本上是相同的解决方案。

第二种方法可以工作,但是要花几个小时才能计算:

def df_diff(newticker: pd.DataFrame):
    times = newticker.index.get_level_values("index")
    timesu = times.unique()
    symbols = newticker.index.get_level_values("name")
    symbolsu = symbols.unique()
    symb_combination = list(itertools.permutations(symbolsu, 2))
    tuple_list = []
    #
    for timet in timesu:
        for sym in symb_combination:
            tuple_list.append((timet, sym[0], sym[1]))
    #
    mindex = pd.MultiIndex.from_tuples(tuple_list,
                                       names=["index", "name1", "name2"])
    cols = newticker.columns
    #
    dfdiff = pd.DataFrame(columns=cols,
                          index=mindex)
    #
    for symt in symb_combination:
        sym1 = symt[0]
        sym2 = symt[1]
        sym1df = newticker.xs(sym1, level='name')
        sym2df = newticker.xs(sym2, level='name')
        symdiff = sym1df.values - sym2df.values
        dfdiff.loc[(slice(None), sym1, sym2), :] = symdiff
    #
    return dfdiff

我敢肯定,有一种更优雅的方式来做我想要的事情。我会寻求任何帮助。

1 个答案:

答案 0 :(得分:1)

您有一个结构良好的数据框,我们需要做的只是merge,然后是groupby

df=newticker.reset_index()# using the index for merge key 

newdf=df.merge(df,on='index')
newdf=newdf.loc[lambda x:['name_x']!=x['name_y']]
newdf=newdf.set_index(['index','name_x','name_y'])

-newdf.groupby(newdf.columns.str.split('_').str[0],
           axis=1).diff().dropna(1)

Out[90]: 
                      a_y  c_y  z_y
index name_x name_y                
0     foo    bar     11.0  7.0 -0.0
             baz      8.0  6.0 -0.0
             toto     3.0  5.0 -0.0
             titi    10.0  8.0 -0.0
      bar    foo    -11.0 -7.0 -0.0
             baz     -3.0 -1.0 -0.0
             toto    -8.0 -2.0 -0.0
             titi    -1.0  1.0 -0.0
      baz    foo     -8.0 -6.0 -0.0
             bar      3.0  1.0 -0.0
             toto    -5.0 -1.0 -0.0
             titi     2.0  2.0 -0.0
      toto   foo     -3.0 -5.0 -0.0
             bar      8.0  2.0 -0.0
             baz      5.0  1.0 -0.0
             titi     7.0  3.0 -0.0
      titi   foo    -10.0 -8.0 -0.0
             bar      1.0 -1.0 -0.0
             baz     -2.0 -2.0 -0.0
             toto    -7.0 -3.0 -0.0
1     foo    bar      4.0  5.0 -0.0
             baz      2.0  3.0 -0.0
             toto     3.0  5.0 -0.0
             titi     2.0  6.0 -0.0
      bar    foo     -4.0 -5.0 -0.0
             baz     -2.0 -2.0 -0.0
             toto    -1.0 -0.0 -0.0
             titi    -2.0  1.0 -0.0
      baz    foo     -2.0 -3.0 -0.0
             bar      2.0  2.0 -0.0
             toto     1.0  2.0 -0.0
             titi    -0.0  3.0 -0.0
      toto   foo     -3.0 -5.0 -0.0
             bar      1.0 -0.0 -0.0
             baz     -1.0 -2.0 -0.0
             titi    -1.0  1.0 -0.0
      titi   foo     -2.0 -6.0 -0.0
             bar      2.0 -1.0 -0.0
             baz     -0.0 -3.0 -0.0
             toto     1.0 -1.0 -0.0