2016-03-31 14 views
1

私は自分の質問に対する答えを見つけようとしましたが、おそらく私の状況に正しく解決策を適用していないことがあります。これは私のデータシートのいくつかの行を所得グループにグループ化するために作成したものです。私は4つの新しいデータフレームを作成し、それぞれにインデックスを適用した後に連結しました。これは最適なのでしょうか、それとも良い方法がありますか?Python/Pandas - 条件別にグループ化する最も良い方法は?

私の目標は、これらの新しいグループとboxpot "by ="引数を使用してboxplotを作成することです。

df_nonull1 = df_nonull[(df_nonull['mn_earn_wne_p6'] < 20000)] 
df_nonull2 = df_nonull[(df_nonull['mn_earn_wne_p6'] >= 20000) & (df_nonull['mn_earn_wne_p6'] < 30000)] 
df_nonull3 = df_nonull[(df_nonull['mn_earn_wne_p6'] >= 30000) & (df_nonull['mn_earn_wne_p6'] < 40000)] 
df_nonull4 = df_nonull[(df_nonull['mn_earn_wne_p6'] >= 40000)] 

df_nonull1['inc_index'] = 1 
df_nonull2['inc_index'] = 2 
df_nonull3['inc_index'] = 3 
df_nonull4['inc_index'] = 4 
frames = [df_nonull1,df_nonull2,df_nonull3,df_nonull4] 
results = pd.concat(frames) 

答えて

1

編集。コメントにPaulが言及したように、ちょうど私の元の答えよりもエレガントなこの種のもののためのpd.cut機能があります。

# equal-width bins 
df['inc_index'] = pd.cut(df.A, bins=4, labels=[1, 2, 3, 4]) 

# custom bin edges 
df['inc_index'] = pd.cut(df.A, bins=[0, 20000, 30000, 40000, 50000], 
         labels=[1, 2, 3, 4]) 

引数は省略可能です。出力(剰余乱数)

A B inc_index 
6 2 16 (0, 7] 
7 5 5 (0, 7] 
3 12 6 (7, 13] 
4 10 8 (7, 13] 
5 9 13 (7, 13] 
1 15 10 (13, 15] 
2 15 7 (13, 15] 
8 15 13 (13, 15] 
0 18 10 (15, 20] 
9 16 12 (15, 20] 

オリジナルソリューション

df = pd.DataFrame(np.random.randint(1, 20, (10, 2)), columns=list('AB')) 
df['inc_index'] = pd.cut(df.A, bins=[0, 7, 13, 15, 20]) 
print df.sort_values('inc_index') 

:あなたは関係なく、ラベルの結果の列でソートできるようpd.cutは、ordered categorical Seriesを生成します。可変バケット幅に対するAlexander's answerの一般化です。 Series.applyを使用してinc_index列を構築できます。例えば、

def bucket(v): 
    # of course, the thresholds can be arbitrary 
    if v < 20000: 
     return 1 
    if v < 30000: 
     return 2 
    if v < 40000: 
     return 3 
    return 4 

df['inc_index'] = df.mn_earn_wne_p6.apply(bucket) 

か、あなたは本当にあなたがちょうど同じバケットにmn_earn_wne_p6の範囲を細分化したい場合は、アレキサンダーの道は非常にクリーンであることをdef

df['inc_index'] = df.mn_earn_wne_p6.apply(
    lambda v: 1 if v < 20000 else 2 if v < 30000 else 3 if v < 40000 else 4) 

注意を避けたい場合はそしてより速い。

df['inc_index'] = df.mn_earn_wne_p6 // bucket_width 

次に、この列で並べ替えることができます。

df.sort_values('inc_index') 

groupby('inc_index')各バケット内で結果を集計することもできます。

+0

うわー、これはまさに私が探していたものです。だから私は関数を定義することは本当に行く方法だと思います。私はラムダのインライン関数を見ていましたが、明らかにそれは複数の基準では機能しません。これは私にも非常に明確に適用されました。私が知っておくべきこのプロセスを行うための他の方法があれば、答えをマークする前にちょっと疑問に思っています。 – user3002486

+0

@ user3002486必要に応じてラムダを使うことができます。私の編集を参照してください。 –

+2

あなたはこのために 'pandas.cut'を使うべきです –

2

すべての値が10Kと50Kの間にある場合、あなたは整数除算(//)を使用してインデックスを割り当てることができます。

df_nonull['inc_index'] = df_nonull.mn_earn_wne_p6 // 10000 

あなたのデータフレームを分割して連結する必要はありませんあなたのmn_earn_wne_p6フィールドからinc_indexを作成する方法を見つける必要があります。

関連する問題