在Pandas Dataframe中,通过Groupby.agg()组合多个列作为lambda函数的参数

时间:2019-12-06 05:37:12

标签: dataframe lambda aggregate pandas-groupby multiple-columns

我希望能够创建一个聚合groupby列,该列是由一个聚合函数创建的,该函数不仅依赖于原始数据帧的一列。例如(在这种情况下),我想计算具有给定半衰期的资产列表的指数加权平均值。

这里是一个示例,其中我根据内置函数计算均值和标准差,并根据lambda函数计算均值...

np.random.seed(0)
df = pd.DataFrame({'DATE': ['2019-11-30','2019-10-31', '2019-09-30', '2019-08-31', '2019-07-31', '2019-06-30',
                            '2019-11-30','2019-10-31', '2019-09-30', '2019-08-31', '2019-07-31', '2019-06-30',
                            '2019-11-30','2019-10-31', '2019-09-30', '2019-08-31', '2019-07-31', '2019-06-30'
                           ],
                    'ASSET': ['ASSET1', 'ASSET1', 'ASSET1', 'ASSET1', 'ASSET1', 'ASSET1',
                              'ASSET2', 'ASSET2', 'ASSET2', 'ASSET2', 'ASSET2', 'ASSET2',
                              'ASSET3', 'ASSET3', 'ASSET3', 'ASSET3', 'ASSET3', 'ASSET3'
                             ],
                   'MARKET_VALUE': [10] * 6 + [15] * 6 + [20] * 6 + np.random.randint(-50,50,18,)/100
                   }
                )

df['DATE'] = df['DATE'].map(lambda x: datetime.datetime.strptime(x, '%Y-%m-%d'))
df['RANK'] = df.groupby('ASSET')['DATE'].rank(ascending=False) - 1
df = df.sort_values(by=['ASSET', 'RANK'])

print(df)

         DATE   ASSET  MARKET_VALUE  RANK
0  2019-11-30  ASSET1          9.94   0.0
1  2019-10-31  ASSET1          9.97   1.0
2  2019-09-30  ASSET1         10.14   2.0
3  2019-08-31  ASSET1         10.17   3.0
4  2019-07-31  ASSET1         10.17   4.0
5  2019-06-30  ASSET1          9.59   5.0
6  2019-11-30  ASSET2         15.33   0.0
7  2019-10-31  ASSET2         14.71   1.0
8  2019-09-30  ASSET2         14.86   2.0
9  2019-08-31  ASSET2         15.37   3.0
10 2019-07-31  ASSET2         15.20   4.0
11 2019-06-30  ASSET2         15.38   5.0
12 2019-11-30  ASSET3         20.38   0.0
13 2019-10-31  ASSET3         19.62   1.0
14 2019-09-30  ASSET3         20.08   2.0
15 2019-08-31  ASSET3         20.15   3.0
16 2019-07-31  ASSET3         19.89   4.0
17 2019-06-30  ASSET3         20.37   5.0

stats = df.groupby('ASSET').agg({'MARKET_VALUE': {'count': 'count',
                                                  'mean': 'mean',
                                                  'std': 'std',
                                                  'meanLambda': (lambda x: x.sum() / x.count()),
                                                  }
                                 }

                                )

print(stats)

stats
       MARKET_VALUE                                
              count       mean       std meanLambda
ASSET                                              
ASSET1            6   9.996667  0.223577   9.996667
ASSET2            6  15.141667  0.287570  15.14167
ASSET3            6  20.081667  0.292124  20.081667

现在我想尝试添加另一个使用'RANK'列以及'MARKET_VALUE'列的lambda函数...

halflife = 6
k = math.log(.5) / halflife
stats = df.groupby('ASSET').agg({'MARKET_VALUE': {'count': 'count',
                                                  'mean': 'mean',
                                                  'std': 'std',
                                                  'mean2': (lambda x: x.sum() / x.count()),
                                                  'ewm': (lambda x: (np.exp(k * df['RANK']) * x).sum())/(np.exp(k * df['RANK'])).sum()
                                                  }
                                 }

                                )

但是我得到一个错误,因为我们只能访问x,即“ MARKET_VALUE”列。

我确实设法成功地将其计算为单列,如下所示...

stats2 = df.groupby('ASSET').agg(lambda x: (np.exp(k * x['RANK']) * x['MARKET_VALUE']).sum() / np.exp(k * x['RANK']).sum())

但是为多个列提供相同的值:

stats2
             DATE  MARKET_VALUE       RANK
ASSET                                     
ASSET1  10.004711     10.004711  10.004711
ASSET2  15.122501     15.122501  15.122501
ASSET3  20.076236     20.076236  20.076236

如果我尝试将其中的一种以上结合在一起,则会出现关键错误:

stats3 = df.groupby('ASSET').agg([lambda x: x['MARKET_VALUE'].count(),lambda x: (np.exp(k * x['RANK']) * x['MARKET_VALUE']).sum() / np.exp(k * x['RANK']).sum()])


 File "C:\Users\p814635\AppData\Local\Programs\Python\Python37\lib\site-packages\pandas\core\indexes\base.py", line 4730, in get_value
    return self._engine.get_value(s, k, tz=getattr(series.dtype, "tz", None))
  File "pandas\_libs\index.pyx", line 80, in pandas._libs.index.IndexEngine.get_value
  File "pandas\_libs\index.pyx", line 88, in pandas._libs.index.IndexEngine.get_value
  File "pandas\_libs\index.pyx", line 128, in pandas._libs.index.IndexEngine.get_loc
  File "pandas\_libs\index_class_helper.pxi", line 91, in pandas._libs.index.Int64Engine._check_type
KeyError: 'MARKET_VALUE'

因此,一般而言,我希望访问agg lambda函数中的任何列(仅返回一列),并具有多个函数的功能(例如meanLambda和stdLambda以及其他统计信息),并且每个统计信息均返回一列每个功能。谢谢。

1 个答案:

答案 0 :(得分:0)

您在egg-info上的做法已经接近。尝试使用pip show <lib-name>代替stats2。然后将其分配回apply的列agg中以合并结果。

'ewm'