Created
November 18, 2024 23:54
-
-
Save ncalm/a0fc974c97acded28f7850f2d816846d to your computer and use it in GitHub Desktop.
This gist shows an example of creating a Power BI-style KPI card using Python in Excel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Create a KPI card | |
card = KPICard(figsize=(4, 3)) | |
# Add elements to the card | |
card.add_title("Revenue") | |
card.add_value(1234567, prefix="$", suffix="") | |
card.add_change(12.5) # Will show with arrow | |
card.add_subtitle("vs. Previous Month") | |
card.add_border() | |
# Show the card | |
card.show() | |
# Clean up | |
card.close() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import matplotlib.pyplot as plt | |
import matplotlib.patches as patches | |
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox | |
import numpy as np | |
class KPICard: | |
""" | |
A class to create KPI card visualizations using matplotlib. | |
""" | |
def __init__(self, figsize=(4, 3), dpi=100): | |
""" | |
Initialize the KPI card with figure size and DPI settings. | |
Args: | |
figsize (tuple): Width and height of the card in inches | |
dpi (int): Dots per inch for the figure | |
""" | |
self.fig, self.ax = plt.subplots(figsize=figsize, dpi=dpi) | |
self.ax.set_xlim(0, 1) | |
self.ax.set_ylim(0, 1) | |
# Remove axes and frame | |
self.ax.axis('off') | |
# Set default colors | |
self.colors = { | |
'background': '#FFFFFF', | |
'title': '#666666', | |
'value': '#000000', | |
'positive': '#28a745', | |
'negative': '#dc3545', | |
'neutral': '#6c757d' | |
} | |
# Set default font sizes | |
self.fontsizes = { | |
'title': 10, | |
'value': 24, | |
'change': 12, | |
'subtitle': 8 | |
} | |
def add_title(self, title, pos=(0.1, 0.8)): | |
"""Add a title to the card""" | |
self.ax.text(pos[0], pos[1], title, | |
fontsize=self.fontsizes['title'], | |
color=self.colors['title'], | |
fontweight='bold') | |
def add_value(self, value, prefix="", suffix="", pos=(0.1, 0.5)): | |
"""Add the main KPI value""" | |
text = f"{prefix}{value}{suffix}" | |
self.ax.text(pos[0], pos[1], text, | |
fontsize=self.fontsizes['value'], | |
color=self.colors['value'], | |
fontweight='bold') | |
def add_change(self, change_value, pos=(0.1, 0.3), show_arrow=True): | |
"""Add the change indicator with optional arrow""" | |
if change_value > 0: | |
color = self.colors['positive'] | |
arrow = "▲" if show_arrow else "" | |
change_text = f"{arrow} +{change_value}%" | |
elif change_value < 0: | |
color = self.colors['negative'] | |
arrow = "▼" if show_arrow else "" | |
change_text = f"{arrow} {change_value}%" | |
else: | |
color = self.colors['neutral'] | |
arrow = "−" if show_arrow else "" | |
change_text = f"{arrow} {change_value}%" | |
self.ax.text(pos[0], pos[1], change_text, | |
fontsize=self.fontsizes['change'], | |
color=color, | |
fontweight='bold') | |
def add_subtitle(self, text, pos=(0.1, 0.2)): | |
"""Add a subtitle or description""" | |
self.ax.text(pos[0], pos[1], text, | |
fontsize=self.fontsizes['subtitle'], | |
color=self.colors['title']) | |
def set_background(self, color=None): | |
"""Set the background color of the card""" | |
if color: | |
self.colors['background'] = color | |
self.fig.patch.set_facecolor(self.colors['background']) | |
self.ax.set_facecolor(self.colors['background']) | |
def add_border(self, color='#EEEEEE', linewidth=1): | |
"""Add a border around the card""" | |
border = patches.Rectangle((0, 0), 1, 1, fill=False, | |
edgecolor=color, linewidth=linewidth) | |
self.ax.add_patch(border) | |
def save(self, filename): | |
"""Save the card to a file""" | |
self.fig.savefig(filename, bbox_inches='tight', | |
facecolor=self.colors['background']) | |
def show(self): | |
"""Display the card""" | |
plt.show() | |
def close(self): | |
"""Close the figure to free memory""" | |
plt.close(self.fig) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment