连载的前两篇文章,小鱼使用 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
是因为 titles
和 images
比 tables
多一项内容。最后一项分析三大活动产生的现金流量净额时,小鱼没有输出表格,因为折线图的展示已经非常直观了。
至此,Word 分析文档就为我们生成好了,下面是小鱼输出的第 1 页内容。
默认输出的文档非常简单,可以根据需要的风格,自行美化 docx 文档,并添加分析结论。
网友评论