2017-08-09 23 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