Python Pandas使用Groupby()创建新列.Sum()

时间:2015-05-14 18:44:40

标签: python pandas

尝试使用groupby计算创建新列。在下面的代码中,我得到了每个日期的正确计算值(请参阅下面的组),但是当我尝试使用它创建一个新列(df [' Data4'])时,我得到了NaN。所以我想在数据框架中创建一个新列,其中包含' Data3'对于所有日期并将其应用于每个日期行。例如,2015-05-08分为2行(总数为50 + 5 = 55),在这个新列中,我想在两行中都有55行。

import pandas as pd
import numpy as np
from pandas import DataFrame


df = pd.DataFrame({'Date': ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'], 'Sym': ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'], 'Data2': [11, 8, 10, 15, 110, 60, 100, 40],'Data3': [5, 8, 6, 1, 50, 100, 60, 120]})

group = df['Data3'].groupby(df['Date']).sum()

df['Data4'] = group

3 个答案:

答案 0 :(得分:141)

您想使用transform这将返回一个索引与df对齐的系列,以便您可以将其添加为新列:

In [74]:

df = pd.DataFrame({'Date': ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'], 'Sym': ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'], 'Data2': [11, 8, 10, 15, 110, 60, 100, 40],'Data3': [5, 8, 6, 1, 50, 100, 60, 120]})
​
df['Data4'] = df['Data3'].groupby(df['Date']).transform('sum')
df
Out[74]:
   Data2  Data3        Date   Sym  Data4
0     11      5  2015-05-08  aapl     55
1      8      8  2015-05-07  aapl    108
2     10      6  2015-05-06  aapl     66
3     15      1  2015-05-05  aapl    121
4    110     50  2015-05-08  aaww     55
5     60    100  2015-05-07  aaww    108
6    100     60  2015-05-06  aaww     66
7     40    120  2015-05-05  aaww    121

答案 1 :(得分:8)

  

如何使用Groupby()。Sum()创建新列?

有两种方法-一种简单明了,另一种更有趣。


每个人的最爱:GroupBy.transform()'sum'

@Ed Chum的回答可以简化一点。呼叫DataFrame.groupby而不是Series.groupby。这样可以简化语法。

# The setup.
df[['Date', 'Data3']]

         Date  Data3
0  2015-05-08      5
1  2015-05-07      8
2  2015-05-06      6
3  2015-05-05      1
4  2015-05-08     50
5  2015-05-07    100
6  2015-05-06     60
7  2015-05-05    120

df.groupby('Date')['Data3'].transform('sum')

0     55
1    108
2     66
3    121
4     55
5    108
6     66
7    121
Name: Data3, dtype: int64 

快一点,

df2 = pd.concat([df] * 12345)

%timeit df2['Data3'].groupby(df['Date']).transform('sum')
%timeit df2.groupby('Date')['Data3'].transform('sum')

10.4 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
8.58 ms ± 559 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

非常规,但值得您考虑:GroupBy.sum() + Series.map()

我偶然发现了API中一个有趣的特质。据我所知,您可以在0.20以上的任何主要版本上重现此代码(我在0.23和0.24上对此进行了测试)。如果您改为使用transform的直接函数并使用GroupBy进行广播,似乎您可以始终节省map所花费的几毫秒时间:

df.Date.map(df.groupby('Date')['Data3'].sum())

0     55
1    108
2     66
3    121
4     55
5    108
6     66
7    121
Name: Date, dtype: int64

比较
df.groupby('Date')['Data3'].transform('sum')

0     55
1    108
2     66
3    121
4     55
5    108
6     66
7    121
Name: Data3, dtype: int64

我的测试表明,如果您有能力使用直接的map函数(例如GroupBymeanminmax等)。在大多数情况下,大约快至20万条记录时,它或多或少地更快。在那之后,性能实际上取决于数据。

(左:v0.23,右:v0.24)

要知道的另类更好,如果您的框架较小且组数较少,则更好。 。 。但我建议将first作为首选。认为这还是值得分享的。

基准代码,供参考:

transform

答案 2 :(得分:0)

df = pd.DataFrame({
'Date' : ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'], 
'Sym'  : ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'], 
'Data2': [11, 8, 10, 15, 110, 60, 100, 40],
'Data3': [5, 8, 6, 1, 50, 100, 60, 120]
})
print(pd.pivot_table(data=df,index='Date',columns='Sym',     aggfunc={'Data2':'sum','Data3':'sum'}))

输出

Data2      Data3     
Sym         aapl aaww  aapl aaww
Date                            
2015-05-05    15   40     1  120
2015-05-06    10  100     6   60
2015-05-07     8   60     8  100
2015-05-08    11  110     5   50