美文网首页
【财报分析】将 Pandas 分析成果输出到 Word 文档

【财报分析】将 Pandas 分析成果输出到 Word 文档

作者: 山药鱼儿 | 来源:发表于2022-02-23 18:49 被阅读0次

    连载的前两篇文章,小鱼使用 Pandas 分析了某上市的三大财务报表:

    • 合并资产负债表
    • 合并利润表
    • 合并现金流量表

    其中,我们输出了大量的表格以及柱形图、折线图。代码、表格、柱形图混在一起未免显得有点儿混乱,尤其我们想要将分析结果共享给其他没有编程背景的同伴,那么代码的出现可能使得同伴非常困惑。

    本节,我们就来学习一下如何将我们之前的输出结果保存到 Word 文档中,更好地呈现分析成果。

    定义常量

    列表 images 中的字符串将作为柱形图(折线图)的标题以及在保存图片文件时进行命名。

    images = [
        ['总资产','总资产增长率'],
        '资产负债率',
        '准货币资金与有息负债',
        ['应付预收与应收预付','应收预付明细'],
        '应收账款和合同资产占总资产的比率',
        '固定资产工程占总资产的比率',
        '投资类资产占总资产的比率',
        '存货和应收账款情况',
        '商誉占总资产的比率',
        ['营业收入','营业收入增长率'],
        ['毛利率','毛利率波动幅度'],
        ['期间费用率','期间费用率占毛利率的比例'],
        '销售费用率',
        ['主营利润率','主营利润占营业利润的比率'],
        '',
        ['净资产收益率ROE','归属于母公司所有者的净利润增长率'],
        '购建支付的现金与经营活动产生的现金流量净额的比率',
        '分配股利、利润或偿付利息支付的现金与经营活动产生的现金流量净额的比率',
        '三大活动的现金流量净额情况'
    ]
    

    定义 Word 文档中显示的标题:

    titles = [
        '看总资产,判断公司实力及扩张能力',
        '看资产负债率,了解公司的偿债风险',
        '看有息负债和准货币资金,排除偿债风险',
        '看“应付预收”减“应收预付”的差额,了解公司的竞争优势',
        '看应收账款、合同资产,了解公司的产品竞争力',
        '看固定资产,了解公司维持竞争力的成本',
        '看投资类资产,判断公司的专注程度',
        '看存货,了解公司未来业绩爆雷的风险',
        '看商誉,了解公司未来爆雷的风险',
        '看营业收入,了解公司的行业地位及成长性',
        '看毛利率,了解公司的产品竞争力及风险',
        '看期间费用率,了解公司的成本管控能力',
        '看销售费用率,了解公司产品的销售难易度',
        '看主营利润,了解公司主业的盈利能力及利润质量',
        '看净利润,了解公司的经营成果及含金量,净利润主要看净利润含金量',
        '看归母净利润,了解公司的整体盈利能力及持续性',
        '看购买固定资产、无形资产和其他长期资产支付的现金,了解公司的增长潜力',
        '看分配股利、利润或偿付利息支付的现金,了解公司的现金分红情况',
        '附:三大活动产生的现金流量净额'
    ]
    

    一共有 19 个标题,前 18 个为三大财务报表的十八步财报排雷,最后一个对应经营活动、投资活动、筹资活动产生的现金流量净额情况。

    定义函数

    我们需要在 Word 文档中依次写入每个分析步骤的标题、表格以及绘图结果。定义函数 save_title save_table save_image

    import docx
    
    def save_table(table):
        rows, cols = table.shape[0]+1, table.shape[1]
        t = doc.add_table(rows, cols) 
    
        # add the header rows. 
        for col in range(cols-1): 
            # 表格部分只取最近5年的数据,从索引1开始取
            t.cell(0, col+1).text = str(table.columns[col+1])
    
        # add the index cols.
        for row in range(rows-1):
            t.cell(row+1, 0).text = str(table.index[row])
    
        # add the rest of the dataframe 
        for row in range(rows-1): 
            for col in range(cols-1): 
                t.cell(row+1,col+1).text = str(table.values[row, col+1]) 
                
        doc.add_paragraph()
        doc.save(DOC)
        
    def save_title(title):
        doc.add_paragraph(title)
        doc.add_paragraph()
        doc.save(DOC)
        
    def save_image(image_path):
        if isinstance(image_path, list):
            for img in image_path:
                doc.add_picture(f'{img}.png')
        elif image_path:
            doc.add_picture(f'{image_path}.png')
        doc.save(DOC)
    

    值得注意的是,对于一些分析项,需要保存的图片可能不止一张,比如资产项的分析中,就有总资产和总资产增长率两张图片。

    函数调用

    首先,将所有的表格搜集到一个列表中:

    tables = [t1_show, t2_show, t3_show, t4_show, t5_show, t6_show, 
              t7_show, t8_show, t9_show, t10_show, t11_show, t12_show,
              t13_show, t14_show, t15_show, t16_show, t17_show, t18_show]
    

    t1_show 为例,展示表格结构:

    t1 = pd.DataFrame(index=debt_df.index, columns=['资产合计(元)', '总资产增长率'])
    t1['资产合计(元)'] = debt_df['资产合计(元)']
    t1['总资产增长率'] = debt_df['资产合计(元)'].pct_change()
    
    t1_show=pd.merge(
        t1.loc[:,['资产合计(元)']].apply(format_thousandth),
        t1.loc[:,['总资产增长率']].apply(format_percentage),
        left_index=True,
        right_index=True
    ).T
    t1_show
    

    在绘图函数中增加 plt.savefig(title+'.png') 语句,将绘制结果先保存成本地 png 图片。

    def format_thousandth(arr):
        """将 arr 或 Series 中的数字使用千分位表示"""
        return arr.apply(lambda x:format(x, ',.0f'))
        
    def format_percentage(arr):
        """将 arr 或 Series 中的数字使用百分之表示,小数点后保留 2 位"""
        return arr.apply(lambda x:format(x, '.2%'))
    
    def plot_show(t, title='', ylabel='单位:亿', kind='line', y_format='hundred million'):
        """绘图"""
        t.plot(kind=kind)
        
        y_max = t.max()
        y_min = t.min()
        while type(y_max) == pd.Series:
            y_max = y_max.max()
            y_min = y_min.min()
        
        if y_min > 0:
            y_min = 0
        
        num_yticks = np.linspace(y_min, y_max, 8)
        if y_format == 'hundred million':
            plt.yticks(num_yticks, map(lambda x:round(x/100000000,2), num_yticks))
        else:
            plt.yticks(num_yticks, map(lambda x:format(x,'.2%'), num_yticks))
            
        if kind == 'line':
            plt.xticks(t.index, t.index)
        
        plt.ylabel(ylabel)
        plt.title(title)
        plt.savefig(title+'.png')
    

    这样,当在 NoteBook 中展示绘制结果时,也会同时生成相应的本地文件:

    plot_show(t1['资产合计(元)'], title=images[0][0], kind='bar')
    

    总资产增长率:

    plot_show(t1['总资产增长率'][1:], title=images[0][1], ylabel='', y_format='p')
    

    调用函数,生成 Word 文档:

    from itertools import zip_longest
    
    DOC = 'xxx公司2020财报排雷.docx'
    doc = docx.Document(DOC) 
    
    for title, table, image in zip_longest(titles, tables, images):
        save_title(title)
        if table is not None:
            save_table(table)
        save_image(image)
    

    使用 zip_longest 是因为 titlesimagestables 多一项内容。最后一项分析三大活动产生的现金流量净额时,小鱼没有输出表格,因为折线图的展示已经非常直观了。

    至此,Word 分析文档就为我们生成好了,下面是小鱼输出的第 1 页内容。

    默认输出的文档非常简单,可以根据需要的风格,自行美化 docx 文档,并添加分析结论。

    相关文章

      网友评论

          本文标题:【财报分析】将 Pandas 分析成果输出到 Word 文档

          本文链接:https://www.haomeiwen.com/subject/okpilrtx.html