将多列作为参数传递给聚合函数groupby

时间:2013-11-10 13:58:33

标签: python python-2.7 pandas

我仍然在努力熟悉大熊猫groupby的操作。将函数传递给agg时,如果传递的聚合函数需要考虑除聚合函数之外的列中的值,该怎么办。

考虑以下数据框示例,其中列出了两位销售人员的产品销售情况:

DateList = np.array( [(datetime.date.today() - datetime.timedelta(7)) + datetime.timedelta(days = x) for x in [1, 2, 2, 3, 4, 4, 5]] + \
[(datetime.date.today() - datetime.timedelta(7)) + datetime.timedelta(days = x) for x in [1, 1, 2, 3, 4, 5, 5]]
Names = np.array(['Joe' for x in xrange(7)] + ['John' for x in xrange(7)])
Product = np.array(['Product1', 'Product1', 'Product2', 'Product2', 'Product2', 'Product3', 'Product3', \
                    'Product1', 'Product2', 'Product2', 'Product2', 'Product2', 'Product2', 'Product3'])
Volume = np.array([100, 0, 150, 175, 15, 120, 150, 75, 0, 115, 130, 135, 10, 120])
Prices = {'Product1' : 25.99, 'Product2': 13.99, 'Product3': 8.99}
SalesDF = DataFrame({'Date' : DateLists, 'Seller' : Names, 'Product' : Product, 'Volume' : Volume})
SalesDF.sort(['Date', 'Seller'], inplace = True)
SalesDF['Prices'] = SalesDF.Product.map(Prices)

在某些日子里,每个卖家销售的商品不止一件。假设您希望将数据集聚合到单日/卖方观察中,并且您希望根据销售量最大的产品进行汇总。要清楚,这对于音量测量来说很简单,只需将最大函数传递给agg即可。然而,为了评估哪个产品和价格将保留意味着确定哪个量度量最高,然后返回值tha对应于该最大值。

当调用agg并引用底层数据框时,我可以通过使用传递给函数的列中的索引值来获得我想要的结果:

def AggFunc(x, df, col1):
        #Create list of index values that index the data in the column passed as x
    IndexVals = list(x.index)

        #Use those index values to create a list of the values of col1 in those index positions in the underlying data frame. 
    ColList = list(df[col1][IndexVals])

        # Find the max value of the list of values of col1
    MaxVal = np.max(ColList)

        # Find the index value of the max value of the list of values of col1
    MaxValIndex = ColList.index(MaxVal)

        #Return the data point in the list of data passed as column x which correspond to index value of the the max value of the list of col1 data
    return list(x)[MaxValIndex]

FunctionDict = {'Product': lambda x : AggFunc(x, SalesDF, 'Volume'), 'Volume' : 'max',\
'Prices': lambda x : AggFunc(x, SalesDF, 'Volume')}

SalesDF.groupby(['Date', "Seller"], as_index = False).agg(FunctionDict)

但我想知道是否有更好的方法可以将'Volume'作为参数传递给聚合Product的函数,而无需获取索引值并从基础数据框中的数据创建列表?有些东西告诉我没有,因为agg将每列作为一个系列传递给聚合函数,而不是数据帧本身。

有什么想法吗?

由于

1 个答案:

答案 0 :(得分:1)

使用.idxmax首先提取正确的索引会更简单吗?

>>> grouped = SalesDF.groupby(["Date", "Seller"])["Volume"]
>>> max_idx = grouped.apply(pd.Series.idxmax)
>>> SalesDF.loc[max_idx]
          Date   Product Seller  Volume  Prices
0   2013-11-04  Product1    Joe     100   25.99
7   2013-11-04  Product1   John      75   25.99
2   2013-11-05  Product2    Joe     150   13.99
9   2013-11-05  Product2   John     115   13.99
3   2013-11-06  Product2    Joe     175   13.99
10  2013-11-06  Product2   John     130   13.99
5   2013-11-07  Product3    Joe     120    8.99
11  2013-11-07  Product2   John     135   13.99
6   2013-11-08  Product3    Joe     150    8.99
13  2013-11-08  Product3   John     120    8.99

idxmax给出第一次出现的最大值的索引。如果你想保留多个产品,如果它们都获得了最大的音量,它会有所不同,更像是

>>> max_vols = SalesDF.groupby(["Date", "Seller"])["Volume"].transform(max)
>>> SalesDF[SalesDF.Volume == max_vols]