2015-09-13 81 views
0

這個問題與貪婪集封面問題不完全相同,但他們有相同的想法。用熊貓做貪婪套裝的最快方法是什麼?

給定一個數據幀熊貓DF1與一列DF [「S」]一組DF2的鍵字組成的:

import numpy as np 
import pandas as pd 
>>> df = pd.DataFrame(np.array([set([1,3,5]), set([1,3,5,6]), set([2,3,4,12]), set([1,3,7]), set([1,15,11]), set([1,16]), set([16])]),columns=['s']) 
>>> df 
        s 
0  set([1, 3, 5]) 
1 set([1, 3, 5, 6]) 
2 set([12, 2, 3, 4]) 
3  set([1, 3, 7]) 
4 set([1, 11, 15]) 
5  set([1, 16]) 
6   set([16]) 
     ... 

>>> df2 = pd.DataFrame(np.array([[1,2,3,3,3,6,4,8,9,10,11,12,13,14,15,16,5,7],[2.,1.,3.,2.,1.,2.,3.,1.,1.,1.,1.,1.,1.,1.,1.,16.,1.,1.]]).T,columns=['key', 'value']) 
>>> df2 
    key value 
0  1  2 
1  2  1 
2  3  3 
3  3  2 
4  3  1 
5  6  2 
6  4  3 
7  8  1 
8  9  1 
9 10  1 
10 11  1 
11 12  1 
12 13  1 
13 14  1 
14 15  1 
15 16  16 
16 5  1 
17 7  1 

    ... 

數據幀DF2以上可以包含重複的鍵。我們選擇最後一個。例如,爲上面的鍵「3」選擇值「1.0」。

我想查找df ['s']的前6行,可以使其對應鍵的值的總和最大,並按照它們的值貢獻排序新數據幀的行。什麼是最快的方法來做到這一點?

對於給定的數據上述設定,則結果數據幀的前兩行應是

df3: 
    set([1,16]) 
    set([12,2,3,4]) 
    ... 

第二上面未設置([16]),因爲「16」已經包含在集合( [1,16]),並且從集合([16])增加的值爲零。

按照該組的鍵的相應值的總和排序。

更新:

爲了使這個簡單的問題,讓我們考慮DF2只包含唯一的密鑰。它可以很容易地基於安德魯的詭計來修復。

+0

您是否對鍵值有合理的界限,例如: 1..N?從那以後,這似乎會減少到一些基本的線性代數,因爲知道熊貓/ numpy可能是最快的方法。你可以有一個len(df1 ['s'])x n矩陣來表示df1 ['s']中的集合,然後是一個n長度的向量來表示df2。 構建集合矩陣可能很煩人,但對於df2'權重'向量,您需要類似df2.drop_duplicates('key',take_last = True)的東西。 –

+0

鑰匙是一些未知的數字。它應該把它們看作字符串,因爲一個鍵可以是「0001」。 – Rex

+0

好吧,你有不同的密鑰數量的約束?你認爲粗糙的尺寸是df1和df2? –

回答

1

假設您沒有太多密鑰,您可以將您的集合列表表示爲稀疏矩陣,併爲每個密鑰添加一列。

In [29]: df = pd.DataFrame([{1:1,3:1,5:1}, {1:1,3:1,5:1,6:1}, {2:1,3:1,4:1,12:1}, {1:1,3:1,7:1}, {1:1,15:1,11:1}, {9:1}, {16:1}]).fillna(0) 

In [30]: df 
Out[30]: 
    1 2 3 4 5 6 7 9 11 12 15 16 
0 1 0 1 0 1 0 0 0 0 0 0 0 
1 1 0 1 0 1 1 0 0 0 0 0 0 
2 0 1 1 1 0 0 0 0 0 1 0 0 
3 1 0 1 0 0 0 1 0 0 0 0 0 
4 1 0 0 0 0 0 0 0 1 0 1 0 
5 0 0 0 0 0 0 0 1 0 0 0 0 
6 0 0 0 0 0 0 0 0 0 0 0 1 

然後代表你的權重作爲一個系列,通過鍵索引:

In [37]: weights = df2.drop_duplicates('key', keep='last').set_index('key')['value'] 

然後重,總結你的套:

In [40]: totals = (df * weights).sum(axis=1) 

In [41]: totals 
Out[41]: 
0  4 
1  6 
2  6 
3  4 
4  4 
5  1 
6 16 
dtype: float64 

然後就是找到頂級的6行:

In [55]: top6 = totals.order(ascending=False).head(6) 

In [56]: top6 
Out[56]: 
6 16 
2  6 
1  6 
4  4 
3  4 
0  4 
dtype: float64 

您可以使用指數回稀疏矩陣,以恢復這臺這些國家是:

In [58]: df.ix[top6.index] 
Out[58]: 
    1 2 3 4 5 6 7 9 11 12 15 16 
6 0 0 0 0 0 0 0 0 0 0 0 1 
2 0 1 1 1 0 0 0 0 0 1 0 0 
1 1 0 1 0 1 1 0 0 0 0 0 0 
4 1 0 0 0 0 0 0 0 1 0 1 0 
3 1 0 1 0 0 0 1 0 0 0 0 0 
0 1 0 1 0 1 0 0 0 0 0 0 0 

你可能不喜歡這種方法,但我想指出有像集,而不是圖元數據結構的幀作爲元素不是特別大熊貓十歲上下,所以建議對問題進行一些翻譯。