2016-12-16 61 views
0

这里是我的pandas.DataFrame:总结值一列从groupedby数据帧中的大熊猫

a b 
0 1 5 
1 1 7 
2 2 3 
3 1 3 
4 2 5 
5 2 6 
6 1 4 
7 1 3 
8 2 7 
9 2 4 
10 2 5 

我想创建一个新的数据帧,将包含由“A”分组的数据,并包含总和每组最大的3个值。

这是我期望的输出。 'B' 的组1最大3倍的值是7,5和4,以及第2组是7,6和5

a 
1 16 
2 18 

df.groupby('a')['b'].nlargest(3) 

给我此输出,

a  
1 1  7 
    0  5 
    6  4 
2 8  7 
    5  6 
    10 5 

df.groupby('a')['b'].nlargest(3).sum() 

给我的总和34(16 + 18)。

我怎样才能与pandas.DataFrame预期的输出?

谢谢!

回答

2

使用apply是做到这一点的方法之一。

In [41]: df.groupby('a')['b'].apply(lambda x: x.nlargest(3).sum()) 
Out[41]: 
a 
1 16 
2 18 
Name: b, dtype: int64 

时序

In [42]: dff = pd.concat([df]*1000).reset_index(drop=True) 

In [43]: dff.shape 
Out[43]: (11000, 2) 

In [44]: %timeit dff.groupby('a')['b'].apply(lambda x: x.nlargest(3).sum()) 
100 loops, best of 3: 2.44 ms per loop 

In [45]: %timeit dff.groupby('a')['b'].nlargest(3).groupby(level='a').sum() 
100 loops, best of 3: 3.44 ms per loop 
+0

有趣的是,看起来时间取决于团体的规模,看我的时间。你可以在你的电脑上测试它吗? – jezrael

+0

看来,如果群体很大 - 你只有'2'大群体,而我'15''申请'更快。 – jezrael

+0

你说得对。我得到了138比140ms。 'apply'对你的测试用例表现稍微好一些。 – Zero

0

使用双groupby - 第二通过a水平MultiIndex

s = df.groupby('a')['b'].nlargest(3).groupby(level='a').sum() 
print (s) 
a 
1 16 
2 18 
Name: b, dtype: int64 

但对我来说是更好:

df.groupby('a')['b'].nlargest(3).sum(level=0) 

谢谢Nickil Maveli

编辑:如果需要顶3再次,使用Series.nlargest

df = pd.DataFrame({'a': [1, 1, 2, 3, 2, 2, 1, 3, 4, 3, 4], 
        'b': [5, 7, 3, 3, 5, 6, 4, 3, 7, 4, 5]}) 

print (df) 
    a b 
0 1 5 
1 1 7 
2 2 3 
3 3 3 
4 2 5 
5 2 6 
6 1 4 
7 3 3 
8 4 7 
9 3 4 
10 4 5 


df = df.groupby('a')['b'].nlargest(3).sum(level=0).nlargest(3) 
print (df) 
a 
1 16 
2 14 
4 12 
Name: b, dtype: int64 

时序

np.random.seed(123) 
N = 1000000 

L2 = np.arange(100) 

df = pd.DataFrame({'b':np.random.randint(20, size=N), 
        'a': np.random.choice(L2, N)}) 

print (df) 

In [22]: %timeit df.groupby('a')['b'].apply(lambda x: x.nlargest(3).sum()) 
10 loops, best of 3: 125 ms per loop 

In [23]: %timeit df.groupby('a')['b'].nlargest(3).groupby(level='a').sum() 
10 loops, best of 3: 121 ms per loop 

In [29]: %timeit df.groupby('a')['b'].nlargest(3).sum(level=0) 
10 loops, best of 3: 121 ms per loop 

np.random.seed(123) 
N = 1000000 

L2 = list('abcdefghijklmno') 

df = pd.DataFrame({'b':np.random.randint(20, size=N), 
        'a': np.random.choice(L2, N)}) 

print (df) 

In [19]: %timeit df.groupby('a')['b'].apply(lambda x: x.nlargest(3).sum()) 
10 loops, best of 3: 97.9 ms per loop 

In [20]: %timeit df.groupby('a')['b'].nlargest(3).groupby(level='a').sum() 
10 loops, best of 3: 96.5 ms per loop 

In [31]: %timeit df.groupby('a')['b'].nlargest(3).sum(level=0) 
10 loops, best of 3: 97.9 ms per loop 

np.random.seed(123) 
N = 1000000 

L2 = list('abcde') 

df = pd.DataFrame({'b':np.random.randint(20, size=N), 
        'a': np.random.choice(L2, N)}) 

print (df) 


In [25]: %timeit df.groupby('a')['b'].apply(lambda x: x.nlargest(3).sum()) 
10 loops, best of 3: 82 ms per loop 

In [26]: %timeit df.groupby('a')['b'].nlargest(3).groupby(level='a').sum() 
10 loops, best of 3: 81.9 ms per loop 

In [33]: %timeit df.groupby('a')['b'].nlargest(3).sum(level=0) 
10 loops, best of 3: 82.5 ms per loop 
+0

这很有用。你可能有兴趣在时机啊,你已经拥有了他们。整齐。 – Zero

+0

'df.groupby('a')['b']。nlargest(3)。总和(级别= 0)' - 稍快 –

+1

@NickilMaveli - 我觉得很好的代码,我从来没有见过它。谢谢。 – jezrael