Creative report designed only with Matplotlib, without office software

Yefeng Xia
Towards Data Science
4 min readJan 4, 2021

--

In this article, our aim is to create an intuitive report with Matplotlib. Attention: during the work, none of the office software will be demanded. What we only use, is Python.

Photo by Isaac Smith on Unsplash

A series of meaningful data plots works usually as ingredients in a report. As spoken, a good chart is better than a speech. If we have obtained these precious ingredients in advance, the last step is how to place them in a proper way.

Of course, we can use Microsoft Word, Powerpoint, etc. But not necessary. Here I present my recipe with Matplotlib.

1. Short introduction of data and charts

image by Author: excel sheets, the total sales from 2018 to 2020

Based on the excel file, we have gotten some representative charts (bar plot and donut plot). If you don't know how to handle this, please check my previous stories. The links are given, please check them one after one if you feel the tasks not easy or new for you.

  1. Introduction to the factory — the data contributor
  2. write data into a data frame with Pandas and plot them
  3. go deeper with data and explore potential information
  4. how to draw a donut plot

Therewith, we have gathered some charts consisting of one bar plot and nine donut plots.

image by Author: bar plot of the total sales from 2018 to 2020.
image by Author: one of the nine donut plots. The donut plots also on Github

2. Design layout and basic setting with Matplotlib

import matplotlib.pyplot as plt
# set font
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = 'STIXGeneral'
# set A4 paper
fig, ax = plt.subplots(figsize=(8.5, 11))
# Decorative Lines
ax.axvline(x=.01, ymin=0, ymax=1, color='#44A0AD', alpha=0.3, linewidth=120)
plt.axvline(x=.99, color='#5244AD', alpha=0.3, linewidth=120)
plt.axhline(y=.95, xmin=0.14, xmax=0.86, color='#446BAD', linewidth=5,alpha=0.3)

# set background color
ax.set_facecolor('white')

# remove axes
plt.axis('off')

If you enter “plt.show()” now, the figure looks like below

Image by Author: report template

Next, we should add content (title, charts, etc.) to the blank paper.

Header = 'Annual Report of XXX Factory'
Contact = 'Reporter:____________ \n\nDate:________________ \n\nPlace:_______________ '
page = 'Page 1'
# add text
plt.annotate(Header, (.22,.98), weight='regular', fontsize=20, alpha=.6 )
plt.annotate(Contact, (.34,.18), weight='bold', fontsize=14,alpha=.6)
plt.annotate(page, (.48,.02), weight='medium', fontsize=10)

#add a vital bar chart
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
import matplotlib.image as mpimg
first_plot = mpimg.imread('barplot3.png')
imagebox1 = OffsetImage(first_plot, zoom=0.4)
a = AnnotationBbox(imagebox1, (0.48, 0.68),frameon=False)
ax.add_artist(a)

Now, the first page of the report is finished.

image by Author: the first page of the report

Similarly, we continue the style on the second page, which should be filled with detailed donut plots for each year.

To make the content clear, we have to arrange the plots neatly.

fig, ax = plt.subplots(figsize=(8.5, 11))

# Decorative Lines
ax.axvline(x=.01, ymin=0, ymax=1, color='#44A0AD', alpha=0.3, linewidth=120)
plt.axhline(y=.95, xmin=0.14, xmax=0.99, color='#446BAD', linewidth=5,alpha=0.3)
# set background color
ax.set_facecolor('white')

# remove axes
plt.axis('off')
Header = 'Annual Report of XXX Factory'
page2= 'Page 2'
# add text
plt.annotate(Header, (.22,.98), weight='regular', fontsize=20, alpha=.6 )
plt.annotate(page2, (.48,.02), weight='medium', fontsize=10)
first_plot = mpimg.imread('donutplot1.png')
imagebox1 = OffsetImage(first_plot, zoom=0.25)
a1 = AnnotationBbox(imagebox1, (0.29, 0.80),frameon=False)
ax.add_artist(a1)
second_plot = mpimg.imread('donutplot2.png')
imagebox2 = OffsetImage(second_plot, zoom=0.25)
b1 = AnnotationBbox(imagebox2, (0.58, 0.80),frameon=False)
ax.add_artist(b1)
third_plot = mpimg.imread('donutplot3.png')
imagebox3 = OffsetImage(third_plot, zoom=0.1875)
c1 = AnnotationBbox(imagebox3, (0.87, 0.80),frameon=False)
ax.add_artist(c1)

fourth_plot = mpimg.imread('donutplot4.png')
imagebox4 = OffsetImage(fourth_plot, zoom=0.25)
a2 = AnnotationBbox(imagebox4, (0.29, 0.50),frameon=False)
ax.add_artist(a2)
fifth_plot = mpimg.imread('donutplot5.png')
imagebox5 = OffsetImage(fifth_plot, zoom=0.25)
b2 = AnnotationBbox(imagebox5, (0.58, 0.50),frameon=False)
ax.add_artist(b2)
sixth_plot = mpimg.imread('donutplot6.png')
imagebox6 = OffsetImage(sixth_plot, zoom=0.1875)
c2 = AnnotationBbox(imagebox6, (0.87, 0.50),frameon=False)
ax.add_artist(c2)
seventh_plot = mpimg.imread('donutplot7.png')
imagebox7 = OffsetImage(seventh_plot, zoom=0.25)
a3 = AnnotationBbox(imagebox7, (0.29, 0.20),frameon=False)
ax.add_artist(a3)
eighth_plot = mpimg.imread('donutplot8.png')
imagebox8 = OffsetImage(eighth_plot, zoom=0.25)
b3 = AnnotationBbox(imagebox8, (0.58, 0.20),frameon=False)
ax.add_artist(b3)
ninth_plot = mpimg.imread('donutplot9.png')
imagebox9 = OffsetImage(ninth_plot, zoom=0.1875)
c3 = AnnotationBbox(imagebox9, (0.87, 0.20),frameon=False)
ax.add_artist(c3)

plt.savefig('report_2.png', dpi=300, bbox_inches='tight')

Therewith, the second page is well decorated with nine donut plots.

image by Author: the second page of the report consisting of detailed data from 2018 to 2020

Additionally, what we can improve is to draw a conclusion of these plots, which I didn't have time to write within the report. For example, due to the covid-19 pandemic, the total sales in 2020 are dramatically falling.

image by Author

3. Summary

In this short article, the approach to generate a report is explained in detail, which doesn’t need Word or Powerpoint. Our report created by Matplotlib presents relevant information directly obtained by data processing and analysis, which means if you are used to processing data in Python, there is no need to switch apps or platforms.

The code is submitted in Github, which you can download and review.

--

--