I have the following code which generates a 3D plot. I am trying to label the plot lines, but they are not ending up where I expect them.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
# Data
names = [
"A", "B", "C", "D", "E", "F",
"G", "H", "I", "J", "K", "L"
]
wins = [
[0, 14, 20, 24, 29, 33, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39],
[0, 7, 13, 17, 23, 27, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
[0, 5, 8, 11, 15, 16, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19],
[0, 7, 11, 17, 20, 25, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29],
[0, 9, 14, 22, 29, 36, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42],
[0, 6, 10, 16, 20, 24, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29],
[0, 7, 13, 20, 26, 31, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34],
[0, 10, 13, 18, 24, 29, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33],
[0, 5, 11, 13, 16, 21, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26],
[0, 12, 15, 18, 21, 25, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
[0, 9, 11, 12, 17, 20, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26],
[0, 15, 20, 25, 27, 33, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37],
]
weeks = [f"Week{i+1}" for i in range(18)] # X-axis categories (nb of weeks)
# Convert names into numerical indices for the Y-axis
x = np.arange(len(weeks)) # X-axis
y = np.arange(len(names)) # Y-axis
wins_array = np.array(wins) # wins accumulated per weeks and per names
# Create a 3D plot
fig = plt.figure(figsize=(18, 18))
ax = fig.add_subplot(111, projection='3d')
# Plot each line and add labels
for i, y_week in enumerate(y):
ax.plot(x, wins_array[i], zs=y_week, zdir='x', label=weeks[i])
# Add shaded area below the line
ax.bar(x, wins_array[i], zs=y_week, zdir='x', alpha=0.1)
# Add labels directly on the curves
for j, my_label in enumerate(wins_array[i]):
ax.text(i, my_label, y_week, f"{my_label}", color="red", fontsize=8, ha="center")
# Customize labels
ax.set_zlabel('Wins') # Z-axis is wins
ax.set_xticks(y) # X-ticks are names
ax.set_xticklabels(names, rotation=45) # Name labels on X-axis
ax.set_yticks(x) # Y-ticks are weeks
ax.set_yticklabels(weeks) # Week labels on Y-axis
plt.show()
This is the current result:
The result I am trying to achieve is something like this:
How do I fix my code to achieve my desired result?
It is easier to separate the drawing and the text annotation:
# Plot each line
for i, y_week in enumerate(y):
ax.plot(x, wins_array[i], zs=y_week, zdir='x', label=weeks[i])
# Add shaded area below the line
ax.bar(x, wins_array[i], zs=y_week, zdir='x', alpha=0.1)
# Add labels directly on the curves
for i in y:
for j, k in zip(x, wins_array[i]):
ax.text(i, j, k, f"{k}", color="red", fontsize=8, ha="center")