2017-07-07 6 views
2

私は(DFと呼ばれる)は、次のデータフレーム持っています。dfの各のuser_idについてはパンダ階層索引のDataFrameGroupBy拠点での選択行

user_id product_id probReorder 
0  1   196   1.0 
1  1  10258   0.9 
2  1  10326   0.1 
3  1  12427   1.0 
4  1  13032   0.3 
... 

を、私はNを保持したいのですが"probReorder"列の中で最大の値を持つ行。また、私はNがuser_idに依存することを望みます。 は私の現在のアプローチでは、私は辞書を持つキーと値のペア(user_idは、int型)です「lastReordNumber」を持っており、次のように私は、行を選択します。

predictions = [] 
for usr,data in df.groupby(by="user_id"): 
    data = data.nlargest(lastReordNumber[usr], "probReorder") 
    predictions.append(data) 
df = pd.concat(predictions) 

問題は、これは本当に遅いことです。データフレームには約13Mの行と200KBのユニークなものがありますuser_idさんのものです。より速く/より良いアプローチがありますか?

EDIT:前のコードは、指定されたUSER_IDためprobReorder列に重複値がある予期しない出力を生成します。例:

probReorder product_id user_id 
0   0.9   1  1 
1   0.9   3  1 
2   0.9   1  1 
3   0.9   3  1 
4   1.0   5  2 
5   0.5   6  2 
6   0.4   7  2 

のuser_id = 2のために私が期待するものですが、USER_ID = 1のために重複した行があります

lastReordNumber = {1:2, 2:3} 
df = pd.DataFrame({"user_id":[1,1,1,2,2,2,2],"probReorder":[0.9,0.6,0.9,0.1,1,0.5,0.4],\ 
    "product_id":[1,2,3,4,5,6,7]}) 

私は出力を得ます。 私の予想される出力は、次のとおり

probReorder product_id user_id 
0   0.9   1  1 
1   0.9   3  1 
2   1.0   5  2 
3   0.5   6  2 
4   0.4   7  2 

これは、各列が完全にソートし、次に切り捨てられたコード

predictions = [] 
for usr,data in df.groupby(by="user_id"): 
    predictions.append(data.sort_values('probReorder', ascending=False).head(lastReordNumber[usr])) 
predictions = pd.concat(predictions, ignore_index=True) 

の単純な部分を使用することによって得ることができます。これも合理的に効率的です。 しかし、nlargest()メソッドの結果をどのように解釈するのかまだ分かりません。

+0

? –

+0

@BobHaffner良い質問です。期待通りにnlargestが動作していないように見え、一部の行を複製しています。テストケースの出力を投稿する必要がありますか? – chubecca

+0

別のuser_idを含む追加のサンプルデータを投稿します。あなたの希望する出力も投稿してください –

答えて

2

あなたはgroupbyheadsort_valuesを使用することができます。

df1 = df.sort_values('probReorder', ascending=False) 
     .groupby('user_id', group_keys=False) 
     .apply(lambda x: x.head([x.name])) 
print (df1) 
    probReorder product_id user_id 
0   0.9   1  1 
2   0.9   3  1 
4   1.0   5  2 
5   0.5   6  2 
6   0.4   7  2 

nlargestと別の解決策:あなたは最大の等しい2つの以上の行を持っている場合はどうなり

df1 = df.groupby('user_id', group_keys=False) 
     .apply(lambda x: x.nlargest(lastReordNumber[x.name], 'probReorder')) 
print (df1) 
    probReorder product_id user_id 
0   0.9   1  1 
2   0.9   3  1 
4   1.0   5  2 
5   0.5   6  2 
6   0.4   7  2 
+0

答えをありがとう。いくつかのコメント:drop_duplicates()は、重複(user_id、product_id)のペアがないので、この場合は何も行いません。あなたの最初のソリューションは、私が編集で提供したソリューションと同等でなければなりませんが、よりエレガントで多分もっと効率的です。私のマシンで2つ目の解決策が正しく動作しない場合は、上記の「間違った」出力が生成されます。それはnlargest()のバグかもしれない、私はそれを見なければならない。 – chubecca

+0

私はあなたのデータを見て、それはいくつかの重複があるようです。そうでない場合は、それが良いです。私の答えが役に立ったら、[accept](http://meta.stackexchange.com/a/5235/295067)を忘れないでください。答えの横にあるチェックマーク( '✓')をクリックしてグレー表示にします記入してください。ありがとう。 – jezrael

+0

私は、( "user_id"、 "product_id")列に重複がないと言っていたので、私が間違っていれば私を修正して、drop_duplicatesへの呼び出しは何もしません。あなたの2つのソリューションは私の2つのソリューションと同等ですが、そのうちの1つは私のシステムでは期待どおりに動作しません。私は元の問題を解決したと考えていますが、nlargest()の問題はまだ分かりません。 – chubecca

関連する問題