2017-08-09 50 views
1

我已經爲我的問題提供了一個解決方案,但我正在尋求一種更快的方法來完成它。優化從不同指標計數

有一個只有兩列的DataFrame。

 In[1]: import pandas as pd 

    In[2]: temp = pd.DataFrame({'id':['a','a','a','b','b','b'],'col1':[1,2,3,1,2,5],'col2':[1,2,4,1,3,4]}).set_index('id') 

    In[3]: temp 

    Out[3]: 
      col1 col2 
    id  
    a  1  1 
    a  2  2 
    a  3  4 
    b  1  1 
    b  2  3 
    b  5  4 

現在,這是我的問題。我想獲得具有兩列最常見值的ID。我目前的解決方案是對如下:

 In[4]: def count_num(table_name): return (sum(table_name.col1==table_name.col2)) 

    In[5]: best_value, best_ans = [0], [0] 

    In[6]: for m in np.unique(temp.index): 
     ...:  temp_ans = count_num(temp.loc[m]) 
     ...:  if temp_ans > best_value[0]: 
     ...:   best_value.append(temp_ans) 
     ...:   best_ans.append(m) 
     ...:   best_value = best_value[1:] 
     ...:   best_ans = best_ans[1:] 

我的小例子,答案是「A」

 In[7]: best_ans 

    Out[7]: ['a'] 

正如你可以找出來,我用一個for循環運行功能的一個指標時間如果有很多不同的索引,它會浪費時間。

我希望我可以做同樣的事情,而不使用循環。

謝謝你的幫助!

+0

在你的榜樣, '1'似乎是最常見的值,但它在行1和行5中都是索引'a'和'b'。看起來,您希望連接級數中所有值的唯一索引值等於中位數,但也許我不明白你的問題。 – Alexander

+0

在我的例子中,我想獲得col1最多的col2 == col2。我想知道的一點是如何在不使用for循環的情況下在這種DataFrame類型中放置函數。 –

回答

0

使用groupby

In [1310]: temp.eq(temp.col1, axis='index').all(axis=1).groupby('id').sum().idxmax() 
Out[1310]: 'a' 

另外,

In [1313]: temp.apply(pd.Series.nunique, axis=1).eq(1).groupby('id').sum().idxmax() 
Out[1313]: 'a' 

以上兩種解決方案非常適用於多列,如果你只兩列就可以

In [1329]: temp.col1.eq(temp.col2).groupby('id').sum().idxmax() 
Out[1329]: 'a' 

詳情:

In [1315]: temp.eq(temp.col1, axis='index') 
Out[1315]: 
    col1 col2 
id 
a True True 
a True True 
a True False 
b True True 
b True False 
b True False 

In [1316]: temp.apply(pd.Series.nunique, axis=1) 
Out[1316]: 
id 
a 1 
a 1 
a 2 
b 1 
b 2 
b 2 
dtype: int64 
+0

這是一個相當小的例子。真正的功能要複雜得多。所以我的問題的關鍵是使用group by和運行一次函數。是對的嗎? –

+0

@LeeTom - 在我看來,需要'真和假'系列,然後''groupby'與'sum'計數'真實',最大索引值使用'idxmax' – jezrael

+1

Jezael是正確的,這種模式可以爲你工作更大問題,並嘗試儘可能地爲您的速度矢量化您的邏輯。 – Zero

0

可以比較列第一,再總結True值與groupbysum然後idxmax獲得最大的價值指數:

print ((temp.col1==temp.col2)) 
id 
a  True 
a  True 
a False 
b  True 
b False 
b False 
dtype: bool 

print ((temp.col1==temp.col2).groupby(level='id').sum()) 

id 
a 2.0 
b 1.0 
dtype: float64 

print ((temp.col1==temp.col2).groupby(level='id').sum().idxmax()) 
a 

什麼是一樣的:

print (temp.col1.eq(temp.col2).groupby(level='id').sum().idxmax()) 
a