2017-10-05 7 views
1

私はこのようなマルチインデックスデータフレーム持っている:私は何をしたいかマルチインデックスデータフレームの列を引く方法は?

import pandas as pd 
import numpy as np 

df = pd.DataFrame({'ind1': list('aaaaaaaaabbbbbbbbb'), 
        'ind2': list('cccdddeeecccdddeee'), 
        'ind3': list(range(3))*6, 
        'val1': list(range(100, 118)), 
        'val2': list(range(70, 88))}) 

df_mult = df.set_index(['ind1', 'ind2', 'ind3']) 

       val1 val2 
ind1 ind2 ind3    
a c 0  100 70 
      1  101 71 
      2  102 72 
    d 0  103 73 
      1  104 74 
      2  105 75 
    e 0  106 76 
      1  107 77 
      2  108 78 
b c 0  109 79 
      1  110 80 
      2  111 81 
    d 0  112 82 
      1  113 83 
      2  114 84 
    e 0  115 85 
      1  116 86 
      2  117 87 

はそれぞれ、それぞれdf_mult.loc['a', ['c', 'd'], :]df_mult.loc['b', ['c', 'd'], :]に対応する値から、df_mult.loc['a', 'e', :]df_mult.loc['b', 'e', :]の値を減算することです。予想される結果は

   val1 val2 
ind1 ind2 ind3    
a c 0  -6 -6 
      1  -6 -6 
      2  -6 -6 
    d 0  -3 -5 
      1  -3 -5 
      2  -3 -5 
    e 0  106 76 
      1  107 77 
      2  108 78 
b c 0  -6 -6 
      1  -6 -6 
      2  -6 -6 
    d 0  -3 -3 
      1  -3 -3 
      2  -3 -3 
    e 0  115 85 
      1  116 86 
      2  117 87 

は理想的には、このような何かが

df_mult.loc['a', ['c', 'd'], :].subtract(df_mult.loc['a', 'e', :]) 

をうまくいくだろうが、これは私にNaNsの多くを提供します。

どうすればよいですか?

+0

はこのPythonの-2.xのですか? –

+0

@WillemVanOnsem:はい、そうです。 – Cleb

答えて

3

アップデート2:kind help of @Divakar

def repeat_blocks(a, repeats=2, block_length=None): 
    N = a.shape[0] 
    if not block_length: 
     block_length = N//2 
    out = np.repeat(a.reshape(N//block_length,block_length,-1), 
        repeats, 
        axis=0) \ 
      .reshape(N*repeats,-1) 
    return out 

In [234]: df_mult.loc[idx[['a','b'], ['c', 'd'], :], :] -= repeat_blocks(df_mult.loc[['a','b'], 'e', :].values) 

In [235]: df_mult 
Out[235]: 
       val1 val2 
ind1 ind2 ind3 
a c 0  -6 -6 
      1  -6 -6 
      2  -6 -6 
    d 0  -3 -3 
      1  -3 -3 
      2  -3 -3 
    e 0  106 76 
      1  107 77 
      2  108 78 
b c 0  -6 -6 
      1  -6 -6 
      2  -6 -6 
    d 0  -3 -3 
      1  -3 -3 
      2  -3 -3 
    e 0  115 85 
      1  116 86 
      2  117 87 

UPDATE:

In [100]: idx = pd.IndexSlice 

In [102]: df_mult.loc[idx['a', ['c', 'd'], :], :] -= \ 
       np.concatenate([df_mult.loc['a', 'e', :].values] * 2) 

In [103]: df_mult 
Out[103]: 
       val1 val2 
ind1 ind2 ind3 
a c 0  -6 -6 
      1  -6 -6 
      2  -6 -6 
    d 0  -3 -3 
      1  -3 -3 
      2  -3 -3 
    e 0  106 76 
      1  107 77 
      2  108 78 
b c 0  109 79 
      1  110 80 
      2  111 81 
    d 0  112 82 
      1  113 83 
      2  114 84 
    e 0  115 85 
      1  116 86 
      2  117 87 

古い(間違った)解答:

In [62]: df_mult.loc['a', 'e', :] -= df_mult.loc['b', 'e', :].values 

In [63]: df_mult 
Out[63]: 
       val1 val2 
ind1 ind2 ind3 
a c 0  100 70 
      1  101 71 
      2  102 72 
    d 0  103 73 
      1  104 74 
      2  105 75 
    e 0  -9 -9 
      1  -9 -9 
      2  -9 -9 
b c 0  109 79 
      1  110 80 
      2  111 81 
    d 0  112 82 
      1  113 83 
      2  114 84 
    e 0  115 85 
      1  116 86 
      2  117 87 
+0

迅速な対応をありがとう。私は何かを見逃すかもしれないが、これは望ましい結果のようには見えない。 – Cleb

+0

私はあなたが何から何を差し引きたいのかよく分かりません... – MaxU

+0

十分に正確ではないことを申し訳ありません。 'ind1'の各値に対して、' ind2'の残りのすべての値から 'e'(' ind2'の中)に対応するすべての値を減算したいと思います。例えば。 '(a、c、0)= 100' - '(a、e、0)= 106'は '-6'になります。 '(a、c、1)= 101' - '(a、e、1)= 107 'も' -6'であり、以下同様です。それはそれをより明確にしますか? – Cleb

2

あなたは何かのようなものをお探しですか? (dfここに等しいdf_mult

idx = pd.IndexSlice 
df.loc[idx['a', ['c', 'd'], :],idx['val1','val2']]=df.loc['a', ['c', 'd'], :].values-np.tile(df.loc['a', 'e', :].values, (2, 1)) 

df 
Out[608]: 
       val1 val2 
ind1 ind2 ind3    
a c 0  -6 -6 
      1  -6 -6 
      2  -6 -6 
    d 0  -3 -3 
      1  -3 -3 
      2  -3 -3 
    e 0  106 76 
      1  107 77 
      2  108 78 
b c 0  109 79 
      1  110 80 
      2  111 81 
    d 0  112 82 
      1  113 83 
      2  114 84 
    e 0  115 85 
      1  116 86 
      2  117 87 
+0

ええ、私たちは同時にそれを投稿しました;-) +1 – MaxU

+1

@MaxUありがとうございました、私はすでにあなたをアップアップしました。あなたが答えたのを見たときに、あなたは問題を解決する鍵を示します。 – Wen

+0

それは動作しているようです、感謝(upvoted)! 'a'のために' b'のために同じことを行う簡単な方法はありますか、 'ind1'のすべての要素をループさせる必要がありますか?また、 'idx ['val1'、 'val2']'を避ける方法はありますか? – Cleb

関連する問題