SLOPE
Excel Usage
=SLOPE(data, labels, title, color_up, color_down, legend)
data(list[list], required): Input data (Labels, Point1, Point2).labels(list[list], required): Labels for the two points.title(str, optional, default: null): Chart title.color_up(str, optional, default: “green”): Increase color.color_down(str, optional, default: “red”): Decrease color.legend(str, optional, default: “false”): Show legend.
Returns (object): Matplotlib Figure object (standard Python) or base64 encoded PNG string (Pyodide).
Examples
Example 1: Simple slope chart
Inputs:
| data | labels | |||
|---|---|---|---|---|
| Product A | 20 | 35 | Before | After |
| Product B | 30 | 25 | ||
| Product C | 15 | 40 |
Excel formula:
=SLOPE({"Product A",20,35;"Product B",30,25;"Product C",15,40}, {"Before","After"})
Expected output:
"chart"
Example 2: Slope chart with title
Inputs:
| data | labels | title | |||
|---|---|---|---|---|---|
| Team A | 100 | 150 | Q1 | Q2 | Quarterly Comparison |
| Team B | 120 | 110 | |||
| Team C | 90 | 140 |
Excel formula:
=SLOPE({"Team A",100,150;"Team B",120,110;"Team C",90,140}, {"Q1","Q2"}, "Quarterly Comparison")
Expected output:
"chart"
Example 3: Slope chart with custom colors
Inputs:
| data | labels | color_up | color_down | |||
|---|---|---|---|---|---|---|
| Cat 1 | 50 | 80 | Start | End | blue | orange |
| Cat 2 | 70 | 60 | ||||
| Cat 3 | 40 | 90 |
Excel formula:
=SLOPE({"Cat 1",50,80;"Cat 2",70,60;"Cat 3",40,90}, {"Start","End"}, "blue", "orange")
Expected output:
"chart"
Example 4: Slope chart with legend
Inputs:
| data | labels | legend | |||
|---|---|---|---|---|---|
| Item 1 | 10 | 20 | 2023 | 2024 | true |
| Item 2 | 25 | 15 | |||
| Item 3 | 30 | 35 |
Excel formula:
=SLOPE({"Item 1",10,20;"Item 2",25,15;"Item 3",30,35}, {2023,2024}, "true")
Expected output:
"chart"
Python Code
import sys
import matplotlib
IS_PYODIDE = sys.platform == "emscripten"
if IS_PYODIDE:
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import io
import base64
import numpy as np
def slope(data, labels, title=None, color_up='green', color_down='red', legend='false'):
"""
Create a slope chart for comparing paired changes across categories.
See: https://matplotlib.org/stable/gallery/lines_bars_and_markers/slope_chart.html
This example function is provided as-is without any representation of accuracy.
Args:
data (list[list]): Input data (Labels, Point1, Point2).
labels (list[list]): Labels for the two points.
title (str, optional): Chart title. Default is None.
color_up (str, optional): Increase color. Valid options: Green, Blue. Default is 'green'.
color_down (str, optional): Decrease color. Valid options: Red, Orange. Default is 'red'.
legend (str, optional): Show legend. Valid options: True, False. Default is 'false'.
Returns:
object: Matplotlib Figure object (standard Python) or base64 encoded PNG string (Pyodide).
"""
def to2d(x):
return [[x]] if not isinstance(x, list) else x
try:
data = to2d(data)
labels_2d = to2d(labels)
if not isinstance(data, list) or len(data) < 1:
return "Error: Data must be a non-empty list"
# Extract category labels and point values
categories = []
point_one = []
point_two = []
for row in data:
if not isinstance(row, list) or len(row) < 3:
continue
try:
categories.append(str(row[0]))
point_one.append(float(row[1]))
point_two.append(float(row[2]))
except (ValueError, TypeError):
continue
if len(categories) == 0 or len(point_one) == 0 or len(point_two) == 0:
return "Error: No valid data rows found (need 3 columns: Label, Point1, Point2)"
# Extract point labels
point_labels = ['Point 1', 'Point 2']
if isinstance(labels_2d, list) and len(labels_2d) > 0:
if isinstance(labels_2d[0], list) and len(labels_2d[0]) >= 2:
point_labels = [str(labels_2d[0][0]), str(labels_2d[0][1])]
elif len(labels_2d) >= 2:
point_labels = [str(labels_2d[0]), str(labels_2d[1])]
# Create figure
fig, ax = plt.subplots(figsize=(8, 8))
# Draw slopes
for i in range(len(categories)):
# Determine color based on slope direction
if point_two[i] > point_one[i]:
color = color_up
elif point_two[i] < point_one[i]:
color = color_down
else:
color = 'gray'
# Draw line
ax.plot([0, 1], [point_one[i], point_two[i]], '-o', color=color, linewidth=2, markersize=8)
# Add category labels
ax.text(-0.05, point_one[i], categories[i], ha='right', va='center', fontsize=9)
ax.text(1.05, point_two[i], categories[i], ha='left', va='center', fontsize=9)
# Set x-axis labels
ax.set_xticks([0, 1])
ax.set_xticklabels(point_labels, fontsize=12, fontweight='bold')
ax.set_xlim(-0.2, 1.2)
# Remove y-axis
ax.set_yticks([])
if title:
ax.set_title(title)
# Handle legend
if legend == "true":
from matplotlib.lines import Line2D
legend_elements = [
Line2D([0], [0], color=color_up, linewidth=2, label='Increase'),
Line2D([0], [0], color=color_down, linewidth=2, label='Decrease')
]
ax.legend(handles=legend_elements, loc="best")
# Clean up spines
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
plt.tight_layout()
if IS_PYODIDE:
buf = io.BytesIO()
plt.savefig(buf, format='png', bbox_inches='tight')
plt.close(fig)
buf.seek(0)
img_base64 = base64.b64encode(buf.read()).decode('utf-8')
return f"data:image/png;base64,{img_base64}"
else:
return fig
except Exception as e:
return f"Error: {str(e)}"