2017-09-02 1 views
0
次のように

私のパンダのデータフレームがある:パンダピボットテーブル

df = pd.DataFrame({"PAR NAME":['abc','def','def','def','abc'], "value":[1,2,3,4,5],"DESTCD":['E','N','E','E','S']}) 

私はPAR NAMEのためのDFを旋回し、その値の%の年齢はDESTCDが「E」であるところから来ているかを調べる必要があります。このような何か(明らかdidntの仕事!)

df.pivot_table(index="PAR NAME",values=["value"],aggfunc={'value':lambda x: (x.sum() if x["DESTCD"]=="E")*100.0/x.sum()}) 

私は現在、ピボットの「価値」と一緒にそれを合計して、分割した後、条件付きの列を追加して、これをやっているが、私のデータベースが巨大である(1ギガバイトの+)より簡単な方法があるはずです。

編集:期待される出力 abc 16.67(abcとEはabcのうち6が6なので) def 77.78(defとEは合計9のdefのうち7です)。あなたはPAR NAMEに基づいて複数のGROUPBY方法を使用して、操作を適用することができます代わりに、ピボットテーブルの

+1

期待する出力を追加できますか – Dark

答えて

1

をしたい場合。出力はデータフレームで、Eでインデックスを作成して答えを得ることができます。私は単に集計を別々に行い、効率的な結合方法を使用しました。

df = pd.DataFrame({"PAR NAME":['abc','def','def','def','abc'], "value":[1,2,3,4,5],"DESTCD":['E','N','E','E','S']}) 

# First groupby 'DESTCD' and 'PAR NAME' 
gb = df.groupby(['DESTCD', 'PAR NAME'], as_index=False).sum() 
print(gb) 
    DESTCD PAR NAME value 
0  E  abc  1 
1  E  def  7 
2  N  def  2 
3  S  abc  5 

gb_parname = gb.groupby(['PAR NAME']).sum() 
out = gb.join(gb_parname, on='PAR NAME', rsuffix='Total') 
print(out) 
    DESTCD PAR NAME value valueTotal 
0  E  abc  1   6 
1  E  def  7   9 
2  N  def  2   9 
3  S  abc  5   6 

out.loc[:, 'derived']= out.apply(lambda df: df.value/df.valueTotal, axis=1) 

print(out) 
    DESTCD PAR NAME value valueTotal derived 
0  E  abc  1   6 0.166667 
1  E  def  7   9 0.777778 
2  N  def  2   9 0.222222 
3  S  abc  5   6 0.833333 

また、比較的効率的な操作

%%timeit 
gb = df.groupby(['DESTCD', 'PAR NAME'], as_index=False).sum() 
gb_parname = gb.groupby(['PAR NAME']).sum() 
out = gb.join(gb_parname, on='PAR NAME', rsuffix='Total') 
out.loc[:, 'derived']= out.apply(lambda df: df.value/df.valueTotal, axis=1) 
100 loops, best of 3: 6.31 ms per loop 
+0

理由を説明できますか?私はこの状態をトップに追加し、それをあなたのものと比較すると、ほぼ同じに見えました(11.2ミリ秒対10ミリ秒)。限り、私が使用している操作は一般的に高効率であることがわかります。すべての計算はgoupbys、join、applyです。私はこれが非常に遅いと予想する理由はない - 私はタイミングでそれを見ない。私は何かが欠けている場合、私は間違っていると証明され、興味があります。 –

+0

通常、私は 'apply'を好まないことがあります。 OPは 'DESTCD == 'E''の行だけを操作したいと思っていました。新しい列を追加する必要はありません。あなたの解決策もいいです。タイミングもマシンによって異なります。私のマシンであなたのソリューションに1.2秒かかった。 – Dark

+0

ありがとう!私はval2のような他のcolsのための異なったaggsを許可するために少しの修正でこれを使用しました: gb = df。( '' value ':合計、' value2 ':ラムダx:len(x)) gb_parname = gb.groupby([' PAR ' (gb_parname、on = 'PAR NAME'、rsuffix = 'Total') out.loc [:, 'derived'] = out.apply (「dd:df.value * 100.0/df.valueTotal、axis = 1」 out [out ["DESTCD"] == 'E'] –

1

(私のデータが巨大かつ効率で述べたように、複数のデータフレームをスライスお勧めいけないしてくださいすることが重要です:)に注意してください)あなたは欲しい。すなわち

new = df[df['DESTCD']=='E'].groupby('PAR NAME')['value'].sum()*100/df.groupby('PAR NAME')['value'].sum() 

出力:

 
PAR NAME 
abc 16.666667 
def 77.777778 
Name: value, dtype: float64 

私はそれが任意のアルファベットに一般化されるので、特に 'E' を参照せずに問題を解決しようとしたタイミング

%%timeit 

df[df['DESTCD']=='E'].groupby('PAR NAME')['value'].sum()*100/df.groupby('PAR NAME')['value'].sum() 
100 loops, best of 3: 4.03 ms per loop 

%%timeit 
df = pd.concat([df]*10000) 
df[df['DESTCD']=='E'].groupby('PAR NAME')['value'].sum()*100/df.groupby('PAR NAME')['value'].sum() 

100 loops, best of 3: 15.6 ms per loop 
+0

ありがとうございます!これは同じように良い解決策であり、私の目的に役立ちます。私は自分のPC上で微妙に速いものに基づいてのみ正しい答えを選択しました –

0

私はまた、選択した答えと同等に効率的であるピボットを経由して質問に答える方法を見つけたのです!他人の便宜のためにここに追加:だけaggfunc

df.pivot_table(index="PAR NAME",values=["value"],aggfunc={'value':lambda x: x[df.iloc[x.index]['DESTCD']=='E'].sum()*100.0/x.sum()}) 

ロジック・ビーイングは、問題のシリーズで動作し、あなたがメインのDFをインデックス経由でそれらを得るまで、他のシリーズを参照することはできません。