2017-03-06 12 views
1

のレベル2上の位置によってパンダのデータフレームをスライス:各カテゴリについては次のように私はマルチインデックスとパンダのデータフレームを持つマルチインデックス

>>> import pandas as pd 
>>> category = ['bar', 'bar', 'bar', 'bar', 'bar', 'baz', 'baz', 'baz', 'baz', 
       'baz', 'baz', 'foo', 'foo', 'foo'] 
>>> timestamp = ['2017-01-01 09:00:00', '2017-01-01 09:01:00', '2017-01-01 09:02:00', 
       '2017-01-01 09:03:00', '2017-01-01 09:04:00', '2016-11-18 03:18:00', 
       '2016-11-18 03:19:00', '2016-11-18 03:20:00', '2016-11-18 03:21:00', 
       '2016-11-18 03:22:00', '2016-11-18 03:23:00', '2017-02-03 20:39:00', 
       '2017-02-03 20:40:00', '2017-02-03 20:41:00'] 
>>> values = [1,1,2,2,2,35,3,3,4,4,4,28,28,28] 
>>> tuples = list(zip(*[category,timestamp])) 
>>> index = pd.MultiIndex.from_tuples(tuples, names=['category', 'timestamp']) 
>>> df = pd.DataFrame(values,index=index,columns=['values']) 
>>> df 
            values 
category timestamp     
bar  2017-01-01 09:00:00  1 
     2017-01-01 09:01:00  1 
     2017-01-01 09:02:00  2 
     2017-01-01 09:03:00  2 
     2017-01-01 09:04:00  2 
baz  2016-11-18 03:18:00  35 
     2016-11-18 03:19:00  3 
     2016-11-18 03:20:00  3 
     2016-11-18 03:21:00  4 
     2016-11-18 03:22:00  4 
     2016-11-18 03:23:00  4 
foo  2017-02-03 20:39:00  28 
     2017-02-03 20:40:00  28 
     2017-02-03 20:41:00  28 

を、私は回数の累積和を見つけたいですこのような値の列の変更、:私はこれをやってみました

       values changed cum_changes 
category timestamp          
bar  2017-01-01 09:00:00  1 False   0 
     2017-01-01 09:01:00  1 False   0 
     2017-01-01 09:02:00  2 True   1 
     2017-01-01 09:03:00  2 False   1 
     2017-01-01 09:04:00  2 False   1 
baz  2016-11-18 03:18:00  35 False   0 
     2016-11-18 03:19:00  3 True   1 
     2016-11-18 03:20:00  3 False   1 
     2016-11-18 03:21:00  4 True   2 
     2016-11-18 03:22:00  4 False   2 
     2016-11-18 03:23:00  4 False   2 
foo  2017-02-03 20:39:00  28 False   0 
     2017-02-03 20:40:00  28 False   0 
     2017-02-03 20:41:00  28 False   0 

df["changes"] = False 
df.iloc[idx[:,1:],1] = df.iloc[idx[:,1:],0] == df.iloc[idx[:,:-1],0] #This doesn't work 
df["cum_changes"] = df["changed"].groupby(level=[0]).cumsum().astype(int) 

しかしunfortun 2行目はうまく動かないこれはlocで値をマルチインデックスする方法と似ていますが、ilocはMultiIndexを同じ方法で処理しないようです。タイムスタンプは各グループで異なり、各グループの長さが異なるためhead()を使用できないため、ラベルでインデックス化できません。 MultiIndexの第2レベルで位置インデックスを行うことは可能ですか?

私が実際に必要とするのは「cum_changes」列です。「変更された」列は単なる中間段階にすぎません。 「cum_changes」列を計算する別の方法がある場合は、それを聞くことに興味があります。私はそれがカテゴリの列を反復することによって行うことができることを知っていますが、これはベクトル化しておくことが可能であるように思われるので、私はループを伴わないソリューションを探しています。

私はこの関連の質問を見つけましたが、私は解決策が実際の位置によってインデックス付けではなく、ラベルにより所定の位置とインデックス作成に対応したラベルを見つけていないので、それが適用されるとは思わない: Slice MultiIndex pandas DataFrame by position

+2

、あなたは 'iloc'を必要としません。 – Psidom

答えて

1

あなたが@Psidom has already said in the commentとしてdiff()を使用することができます: `差分()`関数を使用して結果が0であるかどうかを確認

In [25]: df['x'] = df.groupby(level=0)['values'] \ 
        .apply(lambda x: x.diff().fillna(0).ne(0).cumsum()) 

In [26]: df 
Out[26]: 
           values x 
category timestamp 
bar  2017-01-01 09:00:00  1 0 
     2017-01-01 09:01:00  1 0 
     2017-01-01 09:02:00  2 1 
     2017-01-01 09:03:00  2 1 
     2017-01-01 09:04:00  2 1 
baz  2016-11-18 03:18:00  35 0 
     2016-11-18 03:19:00  3 1 
     2016-11-18 03:20:00  3 1 
     2016-11-18 03:21:00  4 2 
     2016-11-18 03:22:00  4 2 
     2016-11-18 03:23:00  4 2 
foo  2017-02-03 20:39:00  28 0 
     2017-02-03 20:40:00  28 0 
     2017-02-03 20:41:00  28 0 
関連する問題