使用periodindex在具有多索引列的数据框上进行GroupBy

时间:2019-06-12 16:39:14

标签: python pandas dataframe pivot-table pandas-groupby

我有一个pivot_table生成的DataFrame,它的行有一个索引,列的行是MultiIndexMultiIndex的顶层是我在其上进行计算的数据的名称,第二层是该数据的DATE。这些值是这些计算的结果。看起来像这样:

Imgur link - my reputation not high enough to post inline images

我正在尝试按季度(例如Q42018)而不是每一天(数据的本机格式)对数据进行分组。

我发现this帖子使用PeriodIndex和GroupBy将日期的索引转换为四分之一/年的索引非常优雅并且最有意义。

问题是此解决方案适用于仅具有单个索引列的数据框。尝试执行此操作时遇到了问题,因为我的列是一个多索引,并且我不知道如何使它工作。到目前为止,这是我的尝试:

bt = cleaned2018_df.pivot_table(index='Broker',
                                values=['Interaction Id','Net Points'],
                                columns='Date',
                                aggfunc={'Interaction Id':pd.Series.nunique,
                                         'Net Points':np.sum}, 
                                fill_value=0)

pidx = pd.PeriodIndex(bt.columns.levels[1], freq='Q')
broker_qtr_totals = bt.groupby(pidx, axis=1, level=1).sum()

如您所见,我正在获取MultiIndex的第二级,其中包含所有日期,并通过PeriodIndex函数运行它以获取四分之一索引。然后,我将该PeriodIndex传递给groupby,并告诉它对列和日期所在的第二层进行操作。

这将返回ValueError的{​​{1}}响应。而且我知道原因是因为我传递给GroupBy的Grouper and axis must be same length值的长度为x,而数据帧的列轴的长度为2x(因为多重索引的第一级具有2个值)。

我只是迷上了如何正确地将其应用于整个索引的方法。我似乎无法从句法上找出答案,因此我想依靠社区的专业知识来确定是否有人可以帮助我。

如果我的解释不清楚,我们很乐意进一步澄清。预先谢谢你。

1 个答案:

答案 0 :(得分:0)

我发现了这一点,并将发布答案,以防其他人遇到类似问题。我在正确地考虑问题,但是第一次尝试时遇到了一些错误。

长度错误是由于我将对MultiIndex的第二级的显式引用传递给PeriodIndex函数,然后将其传递给groupby。更好的解决方案是使用.get_level_values函数,因为这考虑到了索引的多级性质,并根据更高级别的项目数返回适当的#个值。

例如-如果您的DataFrame的MultiIndex列具有2个级别-并且这2个级别每个包含3个值,则您的表将具有9个列,因为较低级别针对顶级中的每个值进行细分。我最初的解决方案是直接从第二个级别中获取这3个值,而不是全部9个。get_level_values对此进行了纠正。

第二个问题是我只是将这个PeriodIndex对象本身传递给了groupby。那会起作用,但随后它基本上只是忽略了MultiIndex的顶层。因此,您需要确保传递一个列表,其中包含原始的顶层和要分组的新的第二层。

更正的代码:

#use get_level_values instead of accessing levels directly
pIdx = pd.PeriodIndex(bt.columns.get_level_values(1), freq='Q')

# to maintain original grouping, pass in a list of your original top level, 
# and the new second level
broker_qtr_totals = bt.groupby(by=[bt.columns.get_level_values(0), pidx],
                               axis=1).sum()

这有效

imgur link to dataframe image as my rep is too low