zoukankan      html  css  js  c++  java
  • Padas交叉表新增二级分类小计

    Padas的pivot_table做交叉表变换后支持总计功能,但是分类的小计功能需要自己动手实现。
    在实现这个小计的功能时,好好研究了下交叉表的属性,写了下开发流程,当初走了点弯路,总结如下:

    下图是开发前手写的流程:

    按着这个流程开发到中途遇到点麻烦,又转而尝试了其它方式,因为我们的应用是把交叉表导出到html, 调用了to_html方法,所以,想直接在导出的html字符串上面插入小计,最后确认这种注入方式有三个问题:首先不通用,就算实现了注入小计到导出的html,但是支持交叉表下载到excel文件还是没有小计功能(这个是主要问题),其次对字符串操作效率太低,遇到大的交叉表,开销过大,最后实现起来很麻烦,因为交叉表的变化随着index,column,metric的参数不同而不同,相应的导出的html结构也会变化,很难保证不出异常。
    所以最后还是放弃这种尝试,直接操作pandas来变换实现才是最直接,一劳永逸的方式。
    直接贴代码吧:

    def add_subtotal(self, pivot_table):
            indexs = pivot_table.index
            names = indexs.names
            if len(names) < 2:
                return pivot_table
            else:
                columns = pivot_table.columns
                levels = pivot_table.index.levels[0]
                table_splites = []
                for loc in levels:
                    loc_rows = pivot_table.loc[loc]
                    if loc_rows.shape[0] <= 1:
                        loc_rows = loc_rows.reset_index()
                        loc_rows.insert(0, names[0], loc)
                        table_splites.append(loc_rows)
                        continue
                    if loc == '_Total':
                        loc_rows = loc_rows.reset_index()
                        loc_rows.insert(0, names[0], '_Total')
                        table_splites.append(loc_rows)
                        continue
                    
                    total_row = loc_rows[columns].sum()
                    total_row = pd.DataFrame(data=total_row).T
                    total_row.index = ['_Subtotal']
                    loc_rows = loc_rows.reset_index()
                    
                    rev_names = names[::-1]
                    first_name = rev_names[-1]
                    second_name = rev_names[-2]
                    for name in rev_names[:-1]:
                        if name != second_name:
                            _value = ''
                        else:
                            _value = '_Subtotal'
                        total_row.insert(0, name, _value)
                    loc_rows = loc_rows.append(total_row)
                    loc_rows.insert(0, first_name, loc)
                    table_splites.append(loc_rows)
            result = pd.concat(table_splites, ignore_index=True)
            return result.pivot_table(index=names)

    这段代码单独抽出来独立为PivotTable类的一个实力方法,参数为做过交叉表变换后的df(dataframe)对象,返回的也是一个添加了小计后的df。

    如果只有一个Rows,则肯定是不需要分类小计的情况,只有总计_Total。

    当Row大于一个后:

    效果如上。

    二级下多于一项才会出现_Subtotal小计行。

    导出交叉表到excel,如下:

    到此就实现了交叉表新增分类小计功能和导出带有小计功能。

    千里之行始于足下,成长就是守护和付出的过程,人生苦短,我用Python。
  • 相关阅读:
    HDU 1058
    Codeforces 349C
    HDU 2602
    HDU 2571
    HDU 2955
    HDU 2084
    HDU 1003
    HDU 1506 & 1505
    POJ 1854
    HDU 2095
  • 原文地址:https://www.cnblogs.com/JustToNight/p/7518962.html
Copyright © 2011-2022 走看看