2016-03-19 33 views
0

私のデータはIDでグループ化されています。各グループでは、colBによってソートされます。パンダのcomplexby with groupby

colAがブランクで、colDが(2,3、または4)の場合は、 の列を作成し、最後のnonフラグにflag = 1を設定します。 colCのゼロ行colCが非ゼロであるそのグループの他のすべての行でフラグを0に設定します。 特定のグループの(colAがブランクで、colCが0の)行を削除します。

他のすべての 'id'グループに対して上記の手順を繰り返します。

(コーラは非空白である行の場合、私は私が必要なものにフラグを設定することができます)

ここでは、私が持っているデータである。

id colA ColB colC  colD 
1   10  1352.23 2 
1   11  706.87 2 
1   12  1116.6 2 
1   13  0   2 
1   14  0   2 
1   15  0   2 
2   2  6884.03 3 
2   3  2235.97 3 
2   4  3618.04 3 
2   5  11745.42 3 
3 2013 1  345.98  0 

、ここでは、私が希望するものですそれを処理して取得する。

id colA ColB colC  colD flag 
1   10 1352.23  2 0 
1   11 706.87  2 0 
1   12 1116.6  2 1 
2   2 6884.03  3 0 
2   3 2235.97  3 0 
2   4 3618.04  3 0 
2   5 11745.42 3 1 
3 2013 1 345.98  0 0 

このようなグループには、数千ものデータが含まれています。上記の処理を行うためのPythonコードがどのように見えるのかを誰かが助けてくれることを願っています。私はgroupby関数に基本的に精通していますが、上記を行う方法を理解することはできません。


ここに私が使用しようとしているコードがあります。コードはエラーを返します: "AttributeError: 'str'オブジェクトには 'id'属性がありません。"

私は最終的に削除したいcolCのゼロを検出すると "フラグ"をNaNに設定しようとしていますので、後で簡単に削除できます。ここで

def setFlag(grouped): 
    for name, group in grouped: 
     for i in range(group.id.size): 
      drop_candidate = (
        pd.isnull(group.iloc[i]['colA'])& 
        ((group.iloc[i]['colD'] == 2) | 
        (group.iloc[i]['colD'] == 3) | 
        (group.iloc[i]['colD'] == 4) ) 
       ) 

      last_nonZero = group[group != 0].index[-1] 

      if ( (drop_candidate & (group.iloc[i]['colC'] == 0)) ): 
       group['flag'] = np.nan 
      elif ((drop_candidate & (group.iloc[i]['colC'] != 0)) & (last_nonZero != i)): 
       group['flag'] = 0 
      elif last_nonZero == i: 
       group['flag'] = 1 

     return grouped 

df.groupby('id').apply(setFlag) 

再作成したテストデータフレームへのコードです:

import pandas as pd 
import numpy as np 
df = pd.DataFrame.from_items([ 
    ('id', [1,1,1,1,1,1,2,2,2,2,3]), 
    ('colA', [np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,2013]), 
    ('colB', [10,11,12,13,14,15,2,3,4,5,1]), 
    ('colC', [1352.23,706.87,1116.6,0,0,0,6884.03,2235.97,3618.04,11745.42,345.98]), 
    ('colD', [2,2,2,2,2,2,3,3,3,3,0]), 
    ('flag', [np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,]), 
    ]) 
+0

に変更する必要があります。ハイアレキサンダー:最新の試みを投稿しました。 – Learner

+0

サンプルデータフレームを作成するコマンドを追加できますか? –

答えて

0

あなたのプロセスには3つの部分があるように見えます:

1)コーラである行を取り除きますそれはAND論理あれば、あなたのデータフレーム最初

の削減にヌルとCOLC == 0の仕事:

reduced_df = df.loc[(df.colA.notnull()) & (df.colC != 0), :].copy()

それがORロジック場合:

reduced_df = df.loc[(df.colA.notnull()) | (df.colC != 0), :].copy() 

    id colA colB  colC colD flag 
0 1 NaN 10 1352.23  2 NaN 
1 1 NaN 11 706.87  2 NaN 
2 1 NaN 12 1116.60  2 NaN 
6 2 NaN  2 6884.03  3 NaN 
7 2 NaN  3 2235.97  3 NaN 
8 2 NaN  4 3618.04  3 NaN 
9 2 NaN  5 11745.42  3 NaN 
10 3 2013  1 345.98  0 NaN 

2)今、あなたは、グループの最後の列にフラグを付けるれる部分2上で動作する準備が整いました。デフォルトのフラグの値が0であるので、あなたがduplicatedを使用して重複した値を検索し、コーラヌル

reduced_df.loc[~reduced_df.colD.duplicated(keep='last') & reduced_df.colA.isnull(), 'flag'] = 1 

reduced_df 

    id colA colB  colC colD flag 
0 1 NaN 10 1352.23  2  0 
1 1 NaN 11 706.87  2  0 
2 1 NaN 12 1116.60  2  1 
6 2 NaN  2 6884.03  3  0 
7 2 NaN  3 2235.97  3  0 
8 2 NaN  4 3618.04  3  0 
9 2 NaN  5 11745.42  3  1 
10 3 2013  1 345.98  0  0 
+0

ありがとうdmb。これは確かに動作します!私はduplicated()メソッドを知らなかった。あなたのアイデアは、私が 'groupby'出力の行ごとに処理していたトラックから私を逃しました。 – Learner

+0

私は十分なポイントがないので、私は答えを受け入れることができません(私はそうするオプションが表示されません)。結論として、それぞれのグループの行ごとに処理しようとしたときに間違っていたもの、つまりgroupby()の戻り値を指摘できますか?明らかに、行ごとの処理は、私が必要としていたことを実行する最良の方法ではなく、私の最初の計画よりも優れた方法で私の問題を「フレーム化」するのに役立った。しかし、一般的な方法で、行単位でgroupbyからの出力を処理する正しい方法は何ですか?その処理の出力を元のデータフレームを更新するために使用できますか? – Learner

+0

Groupbyは、ほとんどすべての状況下で、集約出力を生成する操作を必要とします(つまり、グループの平均を取ることができますが、単に出力を得ることはできません) - df.groupby( 'some column' {'別の列':ラムダx:x})。あなたはエラー – dmb

0

である。これは、私が思い付いたであることを確認することができる

reduced_df.loc[:, 'flag'] = 0

3)で始まりますapplyメソッドを使用します。私はあなたが求めていることをしていると思う:

df['flag'] = df['colD'].shift(-1) #use as a placeholder to compare consecutive 'colD' vals 
df['flag'] = df.apply(lambda x: 1 if (x['flag']!=x['colD']) & 
        (np.isnan(x['colA'])) & (x['colD']>0) else 0, axis=1) 

私はそれが動作する場合はお知らせください! (npをbtwにインポートするにはnumpyが必要です)。また、2,3 & 4の場合のみに制限したい場合は、最後の部分を(x['colD']>0)から(x['colD']>1) & (x['colD'] < 5)

+0

ありがとうグレッグ。最後の要素をチェックするシフトのテクニックが好きです。 私はcolC = 0でcolAが空である行を削除するロジックを追加して、提案を有効にできます。ヘルプをよろしくお願いいたします。これは、私が「groupby」を使って行単位で処理しているのとは対照的に、よりクリーンな方法を示しています。 – Learner